2010-05-18 71 views
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 
} 

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

会破坏“主MyClass的”采取一切照顾孩子?没有孩子应该能够杀死它的父母,因为我会在我的主程序中使用指针来销毁对象,对吗?

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

谢谢!

回答

4

这个概念很好,但是您发布的代码存在一些问题(尽管我从您对“内联代码”的评论中收集到的,您只是在飞行中编写此代码,而不是将其从可编译的代码中复制出来程序)。

  1. 你需要有a_childrenMyClass指针数组,所以它需要有型MyClass**,你将需要分配它,它适当地为孩子们增加了一个再分配。

  2. delete[] a_children不会删除子项,它会删除包含指向子项的数组的数组。您必须在MyClass析构函数中迭代数组,删除每个子指针,然后删除数组。实际上,使用std::vector<MyClass*>代替代替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; 
}; 

请注意,这并不考虑到孩子会比摧毁他们的父母以外的任何手段被破坏的可能性。

+0

+1用'vector'替换动态儿童数组。 – Brian 2010-05-18 16:50:34

+0

这个矢量超出了我的想法,但似乎并不合逻辑,因为许多MyClass对象将有一个空的子列表(这些将类似于树中的文件)。但它是一个向量:)。 父母的通知也是一个好主意,没有想到通过:s 所以:矢量+亲子知识它是。谢谢! – rubenvb 2010-05-18 17:08:54

0

破坏“Master MyClass”照顾所有的孩子吗?

是的,你是如何编码它会。不过,您可能希望将a_children初始化为NULL或预先分配的内存中的某个空间。

你为什么要问?我需要通过 “迭代”方式遍历所有子目录 ,并找到平台上的所有文件为独立级别。此树的创建将由原生 API处理,其余不会。这是一个好的 想法开始?

只要您考虑到父母/子女树外部的某个人在父母被删除(导致孩子被删除)时有一个指向孩子的指示的情况,就可以查找。这可以优雅地处理吗?这是你必须关心的情况吗?如果是这样,那么你可能不得不考虑摇摆指针。

0

我不是C++专家,但我不认为它是delete[]孩子,如果他们没有分配new[]犹太教。

有关更多详细信息,请参阅the C++ FAQ on memory allocation

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

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]; 

点的实际向量ers将自动销毁。

0

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