限制Light类实例化

时间:2015-04-02 15:11:07

标签: c++ oop opengl static limit

我有一个开箱即用的“Light”类,但我知道OpenGL只允许有限数量的灯在任何时候都有效。根据{{​​1}},最大亮度是8,所以我应该只允许Light类在编译时或运行时被实例化8次。

我尝试了一种尝试解决问题的方法:

glGetIntegerfv(GL_MAX_LIGHTS, ..)

其中sCounter是int Light::sCounter = 0; Light::Light() : // initialiser-list { sCounter++; if (sCounter > getMaxLightCount()) // do something, but what? } static int调用前面提到的OpenGL函数。如果计数器高于最大灯数,则应该发生一些事情;但我不知道应该如何回应。我不能在构造函数中返回NULL或其他东西,但我一直在寻找解决问题的异常;虽然我一般不喜欢异常,因为它使情况过于复杂。我还看过实现一个Manager类,但这会使事情变得反直觉,因为它实际上意味着用户不会调用Light类,而是调用它的管理器。

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

2 个答案:

答案 0 :(得分:2)

如果它没有太多限制,除非使用工厂,否则可能会阻止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;
}

示例输出

你可以在这里看到前三个实例成功但第四个没有成功。但是,第5个确实有效,因为第3个灯已被删除。

005872C0
005872F0
00587320
00000000
00587320

答案 1 :(得分:0)

我认为让任何一个类创建光来维持计数而不是试图在Light类本身内处理它会更有意义。

如果您拥有许多灯具所有者,最好设置某种可以获得灯光的游泳池,如果需要,您甚至可以创建一种机制,通过该机制,一个客户可以请求不同的客户放弃灯光。