我编写了这个使用三种类型的测试代码:struct One
是没有虚拟成员的普通类型,struct Two : One
有一个纯虚函数和一个虚析构函数,struct Three : Two
实现Two
的接口。
#include <iostream>
struct One
{
~One() {
std::cout << "~One()\n";
}
};
struct Two : One
{
virtual ~Two() {
std::cout << "~Two()\n";
}
virtual void test() = 0;
};
struct Three : Two
{
virtual ~Three() {
std::cout << "~Three()\n";
}
virtual void test() {
std::cout << "Three::test()\n";
}
};
int main()
{
Two* two = new Three;
two->test();
One* one = two;
delete one;
}
不出所料,the output was这个:
三个::测试()
〜一()
除了让每个析构函数都虚拟之外,还有什么方法可以解决这个问题吗?或者程序员应该注意不要遇到这种情况?我觉得奇怪的是编译时没有任何警告。
答案 0 :(得分:2)
唯一的“修复”不是通过指向One
的指针删除对象。
如果这是一个经常出现的问题,取决于您的课程的使用方式。例如,标准库包含像unary_function
这样没有虚拟析构函数的结构,但我们几乎没有看到它像这样被滥用。
答案 1 :(得分:2)
delete one
调用未定义的行为,因为对象的动态类型与静态类型不匹配,静态类型没有虚拟析构函数。
避免这样的问题的通常方法是使析构函数成为公共和虚拟,或者是受保护的和非虚拟的(在预期以这种方式使用的类上)。
答案 2 :(得分:1)
你必须小心,让One的析构函数变为虚拟。有些编译器会对此发出警告。
答案 3 :(得分:1)
如果要在派生类中使用析构函数,则必须将它们定义为虚拟。这是唯一的方法。