我是一个新的、自学成才的程序员,我的程序设计和结构一直存在问题。基本问题是释放通过 API 提供给我的资源(例如,必须使用 glDeleteBuffers 函数释放的 OpenGL 缓冲区等),而不会破坏我系统的封装。让我简要介绍一下我的设置:
首先,我的程序使用了一个名为“Engine”的大型“外观”类,其中包含一些用于图形渲染、音频流、事件处理等的子系统。我设计背后的主要思想之一是每个子系统将作为尽可能封装;OpenGL 调用仅存在于图形渲染系统、音频中的 OpenAL 调用等中。
我还想注意资源分配和释放,因此我没有在程序的其他部分使用“新”创建各种资产(图像、声音等),而是在 Engine 类中设置了一些工厂方法,用于创建对象,将这些对象注册到适当的子系统(例如,将图像对象引用发送到可以正确缓冲/注册到 OpenGL 的图形子系统),并返回指向这些对象的智能指针。
class Engine //..simplified for sake of example..//
{
private:
GraphicsSystem graphicsRenderer;
AudioSystem audioRenderer;
//..window, events, etc...//
public:
//ctors.. dtor.. tons of other methods..//
std::shared_ptr<Image> createImage( /*filepath, size info, other params*/ );
/*..both of these call equivalent graphics system functions:*/
bool registerImage( Image & tempImage ); //allocates and registers texture resources..
bool deregisterImage( Image & tempImage ); //frees those same resources upon object destruction..
};
这是其中一种工厂方法可能看起来像的示例。
std::shared_ptr<Image> Engine::createImage( /*params*/ )
{
Image * tempImagePtr = new Image( /*params*/ ); //create..
registerImage( *tempImagePtr ); //register..
return std::shared_ptr<Image>( tempImagePtr ); //return..
}
但这是我遇到的主要问题:我发现很难释放使用 registerImage 函数分配的资源!我想让代码工作,以便客户端只负责从引擎中检索资产对象,资源获取和管理的细节被抽象出来并在资产对象被破坏时自动处理..
以下是我尝试/考虑过的一些选项:
让客户端(Engine 类的用户)负责在删除对象之前调用适当的注销函数。这个对象很容易预先编码,但确实有点糟糕,并且消除了通过工厂方法使用 RAII 样式对象创建的要点。这并不能帮助我实现让客户简单地“获得资产并忘记它”的目标。
将整个引擎的单个实例的引用传递给每个资产类,并允许资产类使用该引用在其析构函数中调用注销函数。这是我之前尝试过的一个解决方案,只是为了确保我有适当的自动资源清理工作正常。它〜工作〜但我不喜欢让资产访问所有引擎调用的想法;当他们所需要的只是在引擎中注册/注销自己的能力时,为每个资产提供这种访问权限似乎有些过火了!
我试图通过将指向正确注册和注销函数的指针传递给资产对象来“清理我的代码”并纠正这种情况。这样,对象可以在构造时注册自己,并在销毁时取消注册。在我尝试之前,这似乎是一个不错的计划。到目前为止,我很难通过资产工厂方法将引擎的非策略方法传递给资产对象!C++ 语法是一团混乱,我对函数指针没有经验(更不用说分发指向非静态方法的指针了),而且它变得如此令人沮丧,以至于我正在考虑回到草率的、破坏抽象的传递策略对整个 Engine 实例的引用!我尝试使用方法名称,我尝试在方法名称前添加一个“&”,添加一个“this”。方法名称之前的关键字等
这是我的一个图像资产构造函数的样子:
Image( std::string filepath ,
void (*ptrRegFunc)(unsigned int * tempTextureID, const sf::Image * const tempSourceImage) ,
void (*ptrDeregFunc)(unsigned int * tempTextureID) );
Image 类包含两个相同类型的指针,起初看起来很好,直到我尝试传递指针......
std::shared_ptr<Image> Engine::createImage( std::string filePath )
{
Image * tempImagePtr = new Image( filePath, ®isterImage, &deregisterImage ); //create and send func ptrs..
return std::shared_ptr<Image>( tempImagePtr ); //return..
}
当然,这并没有编译,我明白为什么:不清楚引用的是哪个 Engine 对象/实例。但我查过并尝试了所有这些不同的 C++ 语法风格;
&(this->registerImage)
&((*this).registerImage)
没有任何效果,而且语法太可怕了,几乎不值得麻烦!
但现在我觉得我又回到了原点;所以我一直在寻找其他可能性。在我的脑海中,这个想法似乎很简单:我只想让每个 Asset 对象能够使用 Engine 对象注册和取消注册自己。
有没有更好/更简单的方法来实现我的目标,而无需让每个资产访问整个引擎类接口?我已经阅读了一些关于Command Pattern的内容,这听起来可能是我正在寻找的东西,但我不确定如何实现该模式,或者它是否真的是我需要的。当然,我也遇到过Function Objects的概念。它们中的任何一个都可以解决我的问题吗?
无论如何,感谢您在这方面与我交谈,我仍在学习,我知道这对你们中的许多人来说可能是简单的事情。如果还有什么我可以解释我想要什么或我当前的系统正在使用什么,请告诉我,我会尽快更新