限光 class 实例化
Limiting Light class instantiations
我有一个开箱即用的 class 'Light',但我知道 OpenGL 一次只允许有限数量的灯处于活动状态。根据 glGetIntegerfv(GL_MAX_LIGHTS, ..)
最大灯数为 8,因此无论是在编译时还是在 运行.
中,我应该只允许灯 class 被实例化最多 8 次
我试过一种尝试解决问题的方法:
int Light::sCounter = 0;
Light::Light() : // initialiser-list
{
sCounter++;
if (sCounter > getMaxLightCount())
// do something, but what?
}
其中sCounter是static int
,getMaxLightCount()
调用上述OpenGL函数。如果计数器高于最大灯数,则应该发生一些事情;但我不知道该如何回应。我不能 return NULL 或构造函数中的其他内容,但我一直在寻找异常来解决问题;尽管我通常不喜欢异常,因为它会使情况过于复杂。我也研究过实现一个管理器 class,但这会使事情违反直觉,因为它实际上意味着用户不会调用 Light class,而是调用其中的管理器。
我有哪些选项可以限制 Light 的实例化数量 class,哪种解决方案可以有效地直观地重用?
我认为让 class 创造光的任何东西保持计数而不是试图在 Light
class 本身内处理它会更有意义。
如果您有很多灯主,最好设置某种可以从中获取灯的池,如果需要,您甚至可以创建一种机制,一个客户端可以通过该机制请求不同的客户端放弃灯.
如果它不是太严格,你可以阻止 Light
class 的实例化,除非使用 factory。下面的示例需要 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 个实例化成功但第 4 个没有。但是,第 5 个确实有效,因为第 3 个灯已被删除。
005872C0
005872F0
00587320
00000000
00587320
我有一个开箱即用的 class 'Light',但我知道 OpenGL 一次只允许有限数量的灯处于活动状态。根据 glGetIntegerfv(GL_MAX_LIGHTS, ..)
最大灯数为 8,因此无论是在编译时还是在 运行.
我试过一种尝试解决问题的方法:
int Light::sCounter = 0;
Light::Light() : // initialiser-list
{
sCounter++;
if (sCounter > getMaxLightCount())
// do something, but what?
}
其中sCounter是static int
,getMaxLightCount()
调用上述OpenGL函数。如果计数器高于最大灯数,则应该发生一些事情;但我不知道该如何回应。我不能 return NULL 或构造函数中的其他内容,但我一直在寻找异常来解决问题;尽管我通常不喜欢异常,因为它会使情况过于复杂。我也研究过实现一个管理器 class,但这会使事情违反直觉,因为它实际上意味着用户不会调用 Light class,而是调用其中的管理器。
我有哪些选项可以限制 Light 的实例化数量 class,哪种解决方案可以有效地直观地重用?
我认为让 class 创造光的任何东西保持计数而不是试图在 Light
class 本身内处理它会更有意义。
如果您有很多灯主,最好设置某种可以从中获取灯的池,如果需要,您甚至可以创建一种机制,一个客户端可以通过该机制请求不同的客户端放弃灯.
如果它不是太严格,你可以阻止 Light
class 的实例化,除非使用 factory。下面的示例需要 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 个实例化成功但第 4 个没有。但是,第 5 个确实有效,因为第 3 个灯已被删除。
005872C0
005872F0
00587320
00000000
00587320