Оптимальный способ самостоятельного удаления объектов QObject - PullRequest
1 голос
/ 01 марта 2012

У меня есть два класса Node и NodeContainer:

class Node: public QObject
{
    NodeContainer* parent;
}

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

    QList<Node*> childNodes;
}

У узла может быть родитель или нет.Какой лучший способ реализовать уничтожение класса Node:

1) Получить доступ к родителю и уничтожить себя оттуда

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

2) Подать сигнал и позволить родителю уничтожитьэто позже

destroy()
{
    if(parent !=0)
    {
        //Once the parent receives it, the parent will delete the child.
        emit parentYouHaveToDeleteChild(this);
    }
    else
    {
        deleteLater(this);
    }
}

Ответы [ 4 ]

1 голос
/ 01 марта 2012

Если сигнал parentYouHaveToDeleteChild подключен к слоту deleteChild, между двумя представленными вами методами нет никакой разницы.Программа не вернется в цикл обработки событий перед вызовом слота.

За исключением того, что второй метод добавляет служебную информацию при вызове сигнала / слота.

1 голос
/ 02 марта 2012

Деревья объектов и собственность

Вы также можете удалить дочерние объекты самостоятельно, и они удалят себя от своих родителей .Например, когда пользователь удаляет панель инструментов, это может привести к тому, что приложение удалит один из его объектов QToolBar, и в этом случае родительский элемент QMainWindow панели инструментов обнаружит изменение и соответствующим образом перенастроит свое пространство экрана.Вы получаете Node и NodeContainer из QObject.QObject уже имеет функцию parent() и встроенное дерево объектов , которое используется для автоматического удаления детей или удаления удаленных детей из родителей.Просто используйте существующий механизм, а не изобретайте колесо.

0 голосов
/ 02 марта 2012

Я бы сделал 1), но в деструкторе Узла, то есть

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

    NodeContainer* parent;
}

Я не думаю, что это хорошая ОО-практика для объекта "совершить самоубийство".Объект, который создает ваши Узлы, должен также удалить их, и через деструктор они также будут удалены из своего потенциального NodeContainer.

Обратите внимание, что если вы не используете сигнал / слоты или механизм родительского контроля Qt,мало смысла делать ваши объекты потомками QObject.Это добавляет накладные расходы без преимуществ.

0 голосов
/ 01 марта 2012

Использовать умный указатель

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

Если вы назначите родительский указатель, он будет удален при уничтожении, если вы этого не сделаете, ничего не произойдет:)

Я бы также рекомендовал использовать умный указатель в списке:

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

, который можно ввести в

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

или что-то лучше

Таким образом, когда элемент удаляется из списка, он автоматически удаляется, то же самое верно и для уничтожения списка.

Для кода без пользовательского интерфейса я настоятельно рекомендую использовать стандартные контейнеры, поскольку они являются стандартными и уменьшают зависимость от библиотеки.

...