Наследование от контейнера с не виртуальным деструктором - PullRequest
0 голосов
/ 27 января 2010

Я пытаюсь использовать предварительные объявления и d-указатели для устранения некоторых включаемых зависимостей. Все работает хорошо, за исключением того, что я использовал определения типа XList для удобства чтения во многих местах (например: typedef QList<X> XList).

Обходной путь для проблемы с предварительным объявлением typedef заключается в использовании наследования: class XList : public QList<X>{};. QList имеет не виртуальный деструктор. Учитывая тот факт, что собственный QStringList Qt наследует QList<QString>, и я не выделяю XLists в куче, вы видите какие-либо проблемы с этим обходным решением? Должен ли я явно запретить выделение кучи для классов XList?

Ответы [ 2 ]

1 голос
/ 27 января 2010

Давайте посмотрим, что произойдет, если мы определим XList следующим образом:

class XList : public QList<X> {};

Следующее будет работать как положено:

  XList* x = new XList;
  delete x;

Однако следующее не будет:

  QList<X>* q = new XList;
  delete q;
Будет вызван деструктор

QList<X>, но не XList, если таковой имеется. Вот что виртуальный деструктор в базовом классе сделает для вас.

Если вы никогда не используете распределение кучи, с вами все будет в порядке, но вы готовите ловушку для сопровождающего, следующего за вами (или даже за вами через несколько месяцев).

Убедитесь, что это предположение задокументировано, и сделайте new оператор *1018* закрытым, чтобы предотвратить создание экземпляров кучи, как вы упомянули.

Безопасной альтернативой будет сделать QList<X> членом вашего XList, то есть: предпочесть инкапсуляцию наследованию.

0 голосов
/ 27 января 2010

QStringList не определяет свой собственный деструктор. В этом случае, даже если QList использовался полиморфно (см. Пример blue.tuxedo), проблем нет, поскольку, хотя деструктор производного класса не будет вызван, не определено ни одного.

В вашем случае, если вам нужен деструктор в производном классе (XList), у вас возникнут проблемы. Предыдущее обсуждение о том, как обойти невозможность переадресации описаний типов, было здесь:

Предварительное объявление определения типа в C ++

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

...