Question

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);
    }
}
Was it helpful?

Solution

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.

OTHER TIPS

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.

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top