1

我正在编写一个包含指向同一类型的父对象的指针的类(想想 Qt 的 QObject 系统)。每个对象都有一个父对象,当子对象被销毁时,父对象不应该被销毁(显然)。

class MyClass
{
public:
    MyClass(const MyClass* ptr_parent): parent(parent){};
    ~MyClass(){ delete[] a_children; };
private:
    const MyClass* ptr_parent; // go to MyClass above
    MyClass* a_children; // go to MyClass below
    size_t sz_numChildren; // for iterating over a_children
}

(请原谅我的内联编码,这只是为了简洁)

摧毁“Master MyClass”会照顾所有孩子吗?没有孩子应该能够杀死它的父母,因为我会在我的主程序中有指向被破坏对象的指针,对吗?

你为什么要问?我需要一种方法来“迭代”所有子目录并在独立于平台的级别上查找所有文件。这棵树的创建将由本机 API 处理,其余的则不会。这是一个好主意吗?

谢谢!

4

5 回答 5

4

这个概念很好,但是您发布的代码有很多问题(尽管我从您关于“内联编码”的评论中了解到,您只是动态编写的,而不是从可编译的程序中复制出来)。

  1. 您需要有a_children一个指针数组MyClass,因此它需要有 type MyClass**,并且您需要在添加子项时适当地分配它并重新分配它。

  2. delete[] a_children不会删除孩子,它会删除包含指向孩子的指针的数组。您必须在MyClass析构函数中遍历数组,删除每个子指针,然后删除数组。std::vector<MyClass*>事实上,使用fora_children代替可能是一个更好的主意MyClass*,因此您不必担心 (1)。但即使使用向量,您仍然需要迭代并删除析构函数中的每个子项。

  3. 您的孩子将需要以某种方式向其父对象“注册”。按照您编写的方式,子对象无法告诉父对象它存在。出于这个原因,您可能无法通过传递const父指针来逃避。

所以,举个例子:

class MyClass {

public:

  MyClass(MyClass* parent) 
    : m_parent(parent) 
  { 
    if (m_parent) m_parent->registerChild(this); 
  }

  ~MyClass() 
  {
    for (std::vector<MyClass*>::const_iterator i = m_children.begin(); 
         i != m_children.end(); ++i) 
    {
      delete *i;
    }
  }

  void registerChild(const MyClass* child) 
  {
    m_children.push_back(child);
  }

private:

  MyClass* m_parent;
  std::vector<const MyClass*> m_children;
};

请注意,这并没有考虑到子节点将通过除破坏其父节点之外的任何方式被破坏的可能性。

于 2010-05-18T16:47:36.567 回答
2

是的,如果您使用以下内容创建孩子:

a_children = new Myclass[sz_numChildren];

删除父级将依次删除所有子级。

但是,由于某些原因,这不是很灵活。

  • 必须在一个连续的数组中一次创建所有子级。您将无法addChild()轻松实现这样的功能。
  • 您将无法从 MyClass 派生并将派生类型存储为子类型,因为它们没有被存储为指针。

我建议使用指向 MyClass 对象的指针向量来存储子对象:

std::vector<MyClass*> a_children;

然后你可以根据需要创建孩子:

a_children.push_back(new MyClass(parent));

并删除所有具有以下内容的孩子:

for(int i=0; i<a_children.size(); i++)
    delete a_children[i];

实际的指针向量将被自动销毁。

于 2010-05-18T16:49:02.513 回答
0

摧毁“Master MyClass”会照顾所有孩子吗?

是的,您将如何对其进行编码。但是,您可能希望将 a_children 初始化为 NULL 或您预先分配的内存中的一些空间。

你为什么要问?我需要一种方法来“迭代”所有子目录并在独立于平台的级别上查找所有文件。这棵树的创建将由本机 API 处理,其余的则不会。这是一个好主意吗?

只要您考虑到父/子树外部的某个人在删除父级时具有指向子级的指针(导致子级被删除),就可以寻求。会/可以优雅地处理吗?这是你必须关心的情况吗?如果是这样,那么您可能不得不考虑悬挂指针。

于 2010-05-18T16:43:33.100 回答
0

我不是 C++ 专家,但我认为delete[]如果孩子们没有分配new[].

有关更多详细信息,请参阅有关内存分配的 C++ 常见问题解答。

但是,否则,该计划看起来是合理的。

于 2010-05-18T16:44:46.357 回答
0

另一个问题是您必须确保实例不能是多个父级的子级,否则销毁父级也可能会破坏属于另一个父级的子级。在您的示例中,由于硬链接、Windows 连接点等原因,子目录可能是多个父目录的子目录,因此您需要确保在这种情况下每个超级目录都会获得自己唯一的子实例对于那个目录。如果可以共享子项,那么您将需要实施某种引用计数方案以防止过早删除。

于 2010-05-18T19:05:17.853 回答