从具有非虚拟析构函数的容器继承

时间:2010-01-27 17:30:32

标签: c++ qt typedef forward-declaration qlist

我正在尝试使用前向声明和d指针来消除一些包含依赖项。一切都运行良好,除了我在许多地方使用XList typedef以便于阅读(例如:typedef QList<X> XList)。

typedef转发声明问题的解决方法是使用继承:class XList : public QList<X>{};。 QList有一个非虚拟析构函数。鉴于Qt自己的QStringList继承QList<QString>并且我没有在堆上分配XLists这一事实,您是否看到此解决方法存在任何问题?我应该明确禁止XList类的堆分配吗?

2 个答案:

答案 0 :(得分:1)

让我们来看看如果我们用这种方式定义XList会发生什么:

class XList : public QList<X> {};

以下内容将按预期工作:

  XList* x = new XList;
  delete x;

但以下情况不会:

  QList<X>* q = new XList;
  delete q;
如果有的话,将会调用

QList<X>的析构函数,但不会调用XList。这就是基类中的虚拟析构函数将为您做的事情。

如果你从不使用堆分配,你应该没事,但是你正在为跟随你的维护者准备一个陷阱(甚至你自己在几个月内)。

确保记录此假设并将XList的{​​{1}}运算符设为私有,以防止您提到的堆实例化。

安全的替代方案是让new成为QList<X>的成员,即:首选封装到继承。

答案 1 :(得分:0)

QStringList没有定义自己的析构函数。在这种情况下,即使QList以多态方式使用(参见blue.tuxedo的示例),也没有问题,因为即使派生类析构函数不会被调用,也没有定义。

在您的情况下,如果您在派生类(XList)中需要析构函数,则会遇到问题。之前的讨论是关于如何避免在此处转发声明类型定义:

Forward declaration of a typedef in C++

如果你可以避免编写派生类,从长远来看你可能会更好。