我正在尝试使用前向声明和d指针来消除一些包含依赖项。一切都运行良好,除了我在许多地方使用XList typedef以便于阅读(例如:typedef QList<X> XList
)。
typedef转发声明问题的解决方法是使用继承:class XList : public QList<X>{};
。
QList有一个非虚拟析构函数。鉴于Qt自己的QStringList继承QList<QString>
并且我没有在堆上分配XLists这一事实,您是否看到此解决方法存在任何问题?我应该明确禁止XList类的堆分配吗?
答案 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++
如果你可以避免编写派生类,从长远来看你可能会更好。