我在C ++ Faq lite中没有看到答案:
如何定义基类,以便每个继承它的类都需要定义析构函数?
我尝试过运行这个程序
struct VDtor { virtual ~VDtor()=0; };
struct Test:VDtor { virtual ~Test(){} };
int main() { delete new Test; return 0; }
http://codepad.org/wFcE71w3 带错误
In function `Test::~Test()':
t.cpp:(.gnu.linkonce.t._ZN4TestD0Ev+0x1e): undefined reference to `VDtor::~VDtor()'
In function `Test::~Test()':
t.cpp:(.gnu.linkonce.t._ZN4TestD1Ev+0x1e): undefined reference to `VDtor::~VDtor()'
那么,有可能吗?
答案 0 :(得分:17)
在某种意义上它是“可能的”(如果你的目标是派生类保持抽象,否则)。但是它不会给你想要的结果:因为如果程序员没有这样做,编译器会隐式地创建一个析构函数。
因此不可以强制派生类'作者显式声明构造函数。
(编辑:注意@chubsdad notes ,你的特定代码中的错误是因为你需要定义基类的显式声明的析构函数。)
编辑:只是为了好玩,是的情况需要显式声明的构造函数。请考虑以下
struct Viral {
struct Dose { };
protected:
~Viral() throw (Dose) { }
};
struct Base {
virtual ~Base() throw() { }
};
struct Derived : Base, Viral { };
此代码将无法编译,因为隐式声明的~Derived
将具有比throw (Dose)
更宽松的异常规范~Base
- 因此它违反了覆盖者不应具有的要求更宽松的异常规范。您需要适当地显式声明析构函数
struct Derived : Base, Viral { ~Derived() throw() { } };
但这并不是解决您问题的方法,因为派生类需要“合作”到从Viral
派生或将其作为非静态数据成员。它也很丑陋:)
编辑:以下似乎是符合标准的方式
struct Viral {
struct Dose { };
protected:
~Viral() throw (Dose) { }
};
struct Base : virtual Viral {
virtual ~Base() throw() { }
};
Clang和GCC(starting with v4.6)拒绝任何具有隐式声明的析构函数的Base
派生类,因为它具有不兼容的异常规范(任何派生类都应直接调用~Viral
,标准说,而不是间接地通过调用~Base
。 Comeau接受了这一点,但我强烈怀疑它在这方面不符合要求。
答案 1 :(得分:1)
每个类都有一个析构函数,无论如何。在基础中声明虚拟析构函数可确保子项具有虚拟析构函数。这并不意味着编码器需要显式地声明析构函数 - 无论如何这都不是一件好事。所有这意味着,如果声明了析构函数,它将是虚拟的。
答案 2 :(得分:1)
struct VDtor { virtual ~VDtor()=0; };
VDtor::~VDtor () { } // <== Implementation.
struct Test:VDtor { ~Test(){} };
int main() { delete new Test; return 0; }
要解决这个错误,你必须像上面那样实际实现VDtor :: ~VDtor()。
答案 3 :(得分:0)
当Test被破坏时,它将调用它的基类析构函数,它不存在。如果没有必要的破坏逻辑,你应该将它声明为空。