2012-03-01 2 views
1

У меня есть два класса Node и NodeContainer:Оптимальный способ самостоятельно удаления QObjects

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); 
    } 
} 
+0

Подключите родителя к «разрушенным» сигналам своих детей и установите указатели, если дети уничтожены с помощью 'deleteLater'. Тогда нет необходимости проверять родителя. Кроме того, ваша схема выглядит очень странно. Вы уверены, что это то, что вы хотите? – pmr

+0

Я делаю небольшой текстовый редактор (с тегами). Если тег решает, что он должен быть уничтожен, ему необходимо попросить его содержать тег, чтобы удалить его. В качестве примера ( Bla bla еще bla bla). Если решает удалить, он должен попросить tag1 удалить его из своего списка childs. – Anton

+0

Вы не хотите использовать ['QDomDocument'] (http://qt-project.org/doc/qt-4.8/qdomdocument.html) вместо написания собственных структур данных? – alexisdm

ответ

1

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

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

0

Использование смарт-указатель

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

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

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

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

, которые могут быть typedeffed в

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

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

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

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

+0

Это больше о том, как объект должен уведомить родителя об его удалении, а затем о том, как удалить сам объект. – Anton

+0

Это звучит как обратный дизайн, обязательно родитель должен иметь ребенка, а родитель должен сообщить ребенку, что он должен быть уничтожен. – 111111

1

Object Trees and ownership

Вы можете также удалять дочерние объекты самостоятельно, и они будут удалены от своих родителей. Например, когда пользователь удаляет панель инструментов, это может привести к удалению одного из его объектов QToolBar, и в этом случае родительский элемент QMainWindow панели инструментов обнаружит изменение и соответствующим образом изменит его экранное пространство.

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

+0

Но его узлы хранят сами объекты и не используют механизм родительского хранения QObject. Кроме того, использование родительского механизма QObject для управления деревьями может быть утомительным из-за всех кастингов, которые должны выполняться. – pmr

+0

@pmr: «Его узлам» не нужно хранить родительский объект, потому что к нему можно получить доступ через 'QObject :: parent()'. Повторное использование существующего механизма займет меньше времени, чем реализация другого, независимо от «утомительности». Кроме того, отливки могут быть завернуты в встроенный метод или два. – SigTerm

0

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

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

    NodeContainer* parent; 
} 

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

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