我正在创建一个类(比方说,C),它将数据(比方说,D)与一个对象(比如说O)联系起来。当O被破坏时,O会通知C它很快将不复存在:( ......之后,当C感觉到它是正确的时候,C将放弃属于O的东西,即D。
如果D可以是任何类型的对象,那么C能够执行“删除D”的最佳方式是什么?如果D是一个对象数组怎么办?
我的解决方案是让D派生自C知道的基类。到时候,C调用删除指向基类的指针。
我还考虑过存储void指针并调用delete,但我发现这是未定义的行为并且不会调用D的析构函数。我认为模板可能是一个新颖的解决方案,但我无法解决这个问题。
这是我到目前为止的C,减去一些细节:
// This class is C in the above description. There may be many instances of C.
class Context
{
public:
// D will inherit from this class
class Data
{
public:
virtual ~Data() {}
};
Context();
~Context();
// Associates an owner (O) with its data (D)
void add(const void* owner, Data* data);
// O calls this when he knows its the end (O's destructor).
// All instances of C are now aware that O is gone and its time to get rid
// of all associated instances of D.
static void purge (const void* owner);
// This is called periodically in the application. It checks whether
// O has called purge, and calls "delete D;"
void refresh();
// Side note: sometimes O needs access to D
Data *get (const void *owner);
private:
// Used for mapping owners (O) to data (D)
std::map _data;
};
// Here's an example of O
class Mesh
{
public:
~Mesh()
{
Context::purge(this);
}
void init(Context& c) const
{
Data* data = new Data;
// GL initialization here
c.add(this, new Data);
}
void render(Context& c) const
{
Data* data = c.get(this);
}
private:
// And here's an example of D
struct Data : public Context::Data
{
~Data()
{
glDeleteBuffers(1, &vbo);
glDeleteTextures(1, &texture);
}
GLint vbo;
GLint texture;
};
};
P.S。如果您熟悉计算机图形和VR,我正在创建一个类,它将对象的每个上下文数据(例如OpenGL VBO ID)与其每个应用程序数据(例如顶点数组)分开,并释放每个上下文适当时间的数据(当匹配的渲染上下文是当前的时候)。
答案 0 :(得分:1)
您正在寻找的是Boost::shared_ptr,或类似的智能指针系统。
答案 1 :(得分:1)
问题在于要求相当模糊,所以很难给出一个好的具体答案。我希望以下有所帮助。
如果您希望数据在其所有者死亡时立即消失,请让所有者删除它(如果C实例需要知道则通知C)。如果您希望C在闲暇时进行删除,您的解决方案看起来很好。在我看来,从数据中获取是正确的。 (当然,正如你所做的那样,~Data()必须是虚拟的。)
如果D是一个对象数组怎么办?这个问题有两种解释。如果你的意思是D总是一个数组,那就让它成为指向Data的指针的数组(或矢量<>)。然后在C :: purge()中走向量并删除对象。如果你的意思是D可以是一个对象数组但也可以是一个对象,那么有两种方法可以去。要么决定它总是一个数组(可能大小为1),要么它是一个单个对象(从Data派生),它可以是一个包装实际对象数组(或指向它们的指针)的类。在后一种情况下,包装类析构函数应该遍历数组并执行删除操作。请注意,如果您希望数组(或向量<>)包含实际对象,而不是指向它们的指针(在这种情况下您不必走数组并手动删除),那么您将具有以下限制。 1.数组中的所有对象必须具有相同的实际类型。 2.您必须将数组声明为该类型。这将失去你对多态性的所有好处。
答案 2 :(得分:0)
要回答这个问题,“如果D是一个对象数组怎么办?”,我建议使用一个矢量<>,但你必须将它与D关联起来:
struct D_vector :D { vector<whatever> vw; };