c++ - 限制 Light 类实例化

标签 c++ oop opengl static limit

我有一个开箱即用的“Light”类,但我知道 OpenGL 只允许在任何时间激活有限数量的灯光。根据 glGetIntegerfv(GL_MAX_LIGHTS, ..) 最大灯光为 8,因此无论是在编译时还是运行时,我都应该只允许 Light 类实例化最多 8 次。

我尝试过一种方法来尝试解决问题:

int Light::sCounter = 0;

Light::Light() : // initialiser-list
{
    sCounter++;

    if (sCounter > getMaxLightCount())
        // do something, but what?
}

其中 sCounter 是一个static int,并且 getMaxLightCount() 调用上述 OpenGL 函数。如果计数器高于最大灯光数量,则应该发生某些情况;但我不知道该如何回应。我无法在构造函数中返回 NULL 或其他内容,但我一直在寻找异常来解决问题;尽管我通常不喜欢异常(exception),因为它使情况变得过于复杂。我还考虑过实现 Manager 类,但这会使事情变得违反直觉,因为它实际上意味着用户不会调用 Light 类,而是调用其中的 Manager。

我有哪些选项可以限制 Light 类的实例化数量,哪种解决方案可以有效地直观地重用?

最佳答案

如果限制不是太严格,您可以阻止 Light 类的实例化,除非使用工厂。以下示例需要 C++11,但可以在没有它的情况下工作(尽管需要更多工作,使用 boost 等)。

即使下面的示例还不够充分,也许它可以给您一些想法。

示例代码

#include <iostream>
#include <functional>
#include <memory>

class Light
{
public:
    using Ptr = std::unique_ptr<Light, std::function<void (Light*)>>;

    static void destroyLight(Ptr light)
    {
        // Do nothing, 'light' will be deleted when it falls out of scope
    }

    static Ptr createLight()
    {
        if (sInstanceCount < MAX_INSTANCE_COUNT)
        {
            ++sInstanceCount;
            return Ptr(new Light(), &Light::destroyLightImpl );
        }
        else
        {
            return Ptr();
        }
    }

private:
    Light() {} // Prevent others from creating instances
    ~Light() {} // Prevent others from deleting instances

    static void destroyLightImpl(Light* light)
    {
        delete light;
        --sInstanceCount;
    }

    static const int MAX_INSTANCE_COUNT = 3;
    static int sInstanceCount;
};

int Light::sInstanceCount = 0;

int main()
{
    Light::Ptr light1 = Light::createLight();
    Light::Ptr light2 = Light::createLight();
    std::cout << light1.get() << "\n";
    std::cout << light2.get() << "\n";

    Light::Ptr light3 = Light::createLight();
    Light::Ptr light4 = Light::createLight();
    std::cout << light3.get() << "\n";
    std::cout << light4.get() << "\n";

    Light::destroyLight(std::move(light3));
    Light::Ptr light5 = Light::createLight();
    std::cout << light5.get() << "\n";

    return 0;
}

输出示例

您可以在此处看到前 3 个实例化成功,但第四个实例化失败。但是,第五个灯确实有效,因为第三个灯已被删除。

005872C0
005872F0
00587320
00000000
00587320

关于c++ - 限制 Light 类实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29416386/

相关文章:

c++ - SOIL2 文件上未解析的外部符号 - 需要 opengl 调用

c++ - 当设置 ItemIsMovable 标志时,子项在 QGraphicsView 中不可移动

c++ - 类中 constexpr 关键字的问题

c# - 禁止通过对象访问类的静态元素的设计原因是什么

c++ - OpenGL实例化绘图如何处理顶点输入限制

c - OpenGL Ubuntu 深度

c++ - 操作的条件运算符?

c++ - 在 Visual Studio Enterprise 2017 中禁用自动生成的评论

c++ - 有没有更简单的方法来使用 C++ 和 OpenGL 显示文本?

python - 当我在 python 中使用 f 字符串时得到不同的输出