1

I have two classes Node and NodeContainer:

class Node: public QObject
{
    NodeContainer* parent;
}

class NodeContainer : QObject
{
    bool deleteChild(Node*child)
    {
        if(childNodes->remove(child))
        {
            deleteLater(child);
        }
    }

    QList<Node*> childNodes;
}

A node can either have a parent or not. What is the better way to implement the destruction of the Node class:

1) Access the parent and destroy himself from there

destroy()
{
    if(parent !=0)
    {
        parent.deleteChild(this);
    }
    else
    {
        deleteLater(this);
    }
}

2) Emit a signal, and let the parent destroy it later

destroy()
{
    if(parent !=0)
    {
        //Once the parent receives it, the parent will delete the child.
        emit parentYouHaveToDeleteChild(this);
    }
    else
    {
        deleteLater(this);
    }
}
Anton
  • 1,181
  • 2
  • 17
  • 27
  • Have the parent hook up to the `destroyed` signals of its children and set the pointers if the children are destroyed through `deleteLater`. No need to check the parent then. Also, your scheme looks really weird. Are you sure that's what you want? – pmr Mar 01 '12 at 19:28
  • I am making a little text editor (with tags). If a tag is decides it has to be destroyed, it needs to ask it containing tag to delete it. As an example ( Bla bla more bla bla ). If decides to be deleted, it has to ask tag1 to remove it from its childs list. – Anton Mar 01 '12 at 19:32
  • Are you sure you don't want to use a [`QDomDocument`](http://qt-project.org/doc/qt-4.8/qdomdocument.html) instead of writing your own data structures ? – alexisdm Mar 03 '12 at 03:07

4 Answers4

1

If the parentYouHaveToDeleteChild signal is connected to the deleteChild slot, there is effectively no difference between the two methods you've presented. The program will not return to the event loop before calling the slot.

Except that the second method adds the overhead of a signal/slot call.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
kenrogers
  • 1,350
  • 6
  • 17
1

Object Trees and ownership

You can also delete child objects yourself, and they will remove themselves from their parents. For example, when the user removes a toolbar it may lead to the application deleting one of its QToolBar objects, in which case the tool bar's QMainWindow parent would detect the change and reconfigure its screen space accordingly.

You derive Node and NodeContainer from QObject. QObject already has parent() function and built-in object tree that is used for deleting children automatically or removing deleted children from parents. Simply utilize existing mechanism instead of reinventing the wheel.

SigTerm
  • 26,089
  • 6
  • 66
  • 115
  • But his Nodes are storing the objects themselves and don't use the QObject parent storage mechanism. Also, using the QObject parent mechanism to manage trees can be tedious due to all the casting that has to be performed. – pmr Mar 01 '12 at 20:48
  • @pmr: "His nodes" don't need to store parent object, because it can be accessed via `QObject::parent()`. Reusing existing mechanism will take less time than implementing another one, regardless of "tediousness". Besides, casts can be wrapped into inline method or two. – SigTerm Mar 01 '12 at 22:00
0

Use a smart pointer

class Node: public QObject
{
    std::unique_ptr<Node> parent;
}

If you assign to the parent pointer it will delete on destruction, if you don't then nothing will happen :)

I would also recommend using the smart pointer in the list too:

std::list<std::unique_ptr<node> > node_list;

which can be typedeffed to

typedef std::unique_ptr<node> node_up_t;
typedef std::list<node_up_t>  node_list_t;

or something better

this way, when the element is removed from the list it will automatically be deleted, the same is true of when the list is destroy.

For non UI code I would strong recommend that you use standard containers, because they are standard and reduce the dependency on a library.

111111
  • 15,686
  • 6
  • 47
  • 62
  • It is more about how the objet have to notify the parent about its removal, then about how to delete the object itself. – Anton Mar 01 '12 at 19:34
  • This sounds like backwards design, sure the parent should own the child, and the parent should tell the child that it is to be destroyed. – 111111 Mar 01 '12 at 19:57
0

I would do 1), but in the destructor of Node, i.e.

class Node: public QObject
{
public:
    ~Node ()
    {
        if(parent !=0)
        {
            parent.deleteChild(this);
        }
    }

    NodeContainer* parent;
}

I don't think it is good OO practice for an object to "commit suicide". The object who creates your Node's should also delete them, and via the destructor, they will also be removed from their potential NodeContainer.

Note that if you don't use signal/slots nor Qt parenting mechanism, there is little point making your objects descendants of QObject. It adds overhead without benefits.

Chris Browet
  • 4,156
  • 20
  • 17