亲子计划

发布于 2024-09-01 15:40:59 字数 614 浏览 10 评论 0原文

我正在编写一个类,它保存指向相同类型的父对象的指针(想想 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 处理,其余的则不会。这是一个好主意吗?

谢谢!

I'm writing a class that holds a pointer to a parent object of the same type (think Qt's QObject system). Each object has one parent, and the parent should not be destroyed when a child is destroyed (obviously).

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
}

(Excuse my inline coding, it's only for brevity)

Will destroying the "Master MyClass" take care of all children? No child should be able to kill it's parent, because I would then have pointers in my main program to destroyed objects, correct?

Why might you ask? I need a way to "iterate" through all subdirectories and find all files on a platform independent level. The creation of this tree will be handled by native API's, the rest won't. Is this a good idea to start with?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

顾挽 2024-09-08 15:40:59

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

  1. 您需要将 a_children 设为 MyClass 指针数组,因此它需要具有 MyClass** 类型,并且您当添加子项时,需要适当地分配它并重新分配它。

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

请注意,这并没有考虑到子级将被除摧毁其父级之外的任何方式摧毁的可能性。

This concept is fine, but there are a number of things wrong with the code you posted (although I gather from your comment about "inline coding" that you just wrote this on the fly rather than copying it out of a compilable program).

  1. You will need to have a_children be an array of MyClass pointers, so it will need to have type MyClass**, and you will need to allocate it an reallocate it appropriately as children are added.

  2. delete[] a_children will not delete the children, it will delete the array that holds the pointers to the children. You must, in the MyClass destructor, iterate over the array, deleting each child pointer, and then delete the array. In fact, it would probably be a better idea to use a std::vector<MyClass*> for a_children instead of MyClass*, so then you don't have to worry about (1). But even with a vector, you will still need to iterate and delete each child in the destructor.

  3. Your children will need to "register" with their parent object somehow. The way you have written this, there is no way for the child object to tell the parent object that it exists. For this reason you probably will not be able to get away with passing a const parent pointer.

So, as an example:

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

Note that this does not take into account the possibility that children will be destroyed by any means other than destroying their parent.

‘画卷フ 2024-09-08 15:40:59

是的,如果您使用以下命令创建子项:

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

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

Yes, if you create the children with:

a_children = new Myclass[sz_numChildren];

deleting a parent will in turn delete all children.

However, this will not be very flexible for a few reasons.

  • Children will have to be created all at once in a contiguous array. You won't be able to implement a function like addChild() very easily.
  • You will not be able to derive from MyClass and store the derived types as children since they are not being stored as pointers.

I would recommend using a vector of pointers to MyClass objects to store the children:

std::vector<MyClass*> a_children;

Then you can create children as needed:

a_children.push_back(new MyClass(parent));

and delete all children with:

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

The actual vector of pointers will be destroyed automatically.

花期渐远 2024-09-08 15:40:59

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

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

你为什么会问?我需要一种方法
“迭代”所有子目录
并查找平台上的所有文件
独立水平。的创建
这棵树将由本地人处理
API,其余的不会。这是一个好的
从什么开始?

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

Will destroying the "Master MyClass" take care of all children?

Yes how you have it coded it will. You may however wish to initialize a_children to NULL or to some space in memory you have preallocated.

Why might you ask? I need a way to
"iterate" through all subdirectories
and find all files on a platform
independent level. The creation of
this tree will be handled by native
API's, the rest won't. Is this a good
idea to start with?

Seeks ok so long as you have taken into account the case where someone external to your parent/child tree has a pointer to a child when the parent is deleted (resulting in the child being deleted). Will/can this be handled gracefully? Is this a situation you have to be concerned with? If so then you may have to think about dangling pointers.

甜嗑 2024-09-08 15:40:59

我不是 C++ 专家,但我认为如果没有为子级分配 new[],则删除它们是不明智的。

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

然而,除此之外,该计划看起来还不错。

I'm not a C++ expert but I don't think it's kosher to delete[] the children if they weren't allocated with new[].

See the C++ FAQ on memory allocation for more details.

However, otherwise, the plan looks sound.

当梦初醒 2024-09-08 15:40:59

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

Another gotcha is that you must make sure that an instance cannot be a child of more than one parent, or else destroying a parent could also destroy children belonging to another parent. In your example, a child directory could be a subdirectory of more than one parent directory due to hard links, Windows junction points or the like, so you need to either make sure that in such a situation each superdirectory would get its own unique child instance for that directory. If children can be shared, then you will need to implement some sort of reference counting scheme to prevent premature deletion.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文