在我看到的关于多态的所有例子中,基类的析构函数是virtual
,并且它是用空体定义的。
我正试图解决这个问题:为什么它必须是一个空体?如果方法只是声明为virtual
但没有用emtpy体定义,为什么它不起作用?那么默认的析构函数不能实现吗?或者它被声明为virtual
的事实甚至会压制默认定义并强制明确定义正文?
这就是我的意思:
class A {
public:
virtual void f();
virtual ~A() {}
}
class B : public A {
public:
~B() {
// destroy whatever
}
}
为什么在没有定义的情况下,~A()
可以像virtual ~A();
一样宣布?
另外,为什么必须在抽象类中定义它(使用空体)?我试图声明像virtual ~A() = 0
这样的抽象类的destuctor,编译器不允许我这样做。
答案 0 :(得分:7)
为什么
~A()
在没有定义的情况下不能像virtual ~A();
那样被宣布?
因为无法调用未定义的函数。就那么简单。如果您没有声明析构函数,则编译器会隐式定义一个。但是如果您自己提供声明,则编译器不再提供定义。您可以在C ++ 11中明确地给它默认定义。
virtual ~A() = default;
另外,为什么必须在抽象类中定义它(使用空体)?我试图声明像这个
virtual ~A() = 0
的抽象类的destuctor,编译器不允许我这样做。
同样的道理。只要调用析构函数,它就需要有一个定义,就像任何其他函数一样。通常从不调用纯虚函数,但析构函数是一个例外。您必须提供定义。
class A {
// ...
virtual ~A() = 0; // declare destructor as pure virtual
};
// ...
A::~A() {} // define destructor
答案 1 :(得分:1)
析构函数必须有一个body,因为它在对象被销毁时被调用。每次销毁派生对象时,最后一步是调用基类的析构函数。如果没有正文,链接器就无法找到该析构函数的定义,并且调用失败,就像没有定义的普通函数一样。
完全有可能(并且必须禁止一些模糊的用法)给一个纯粹的虚拟析构函数:
class Foo {
public:
virtual ~Foo() = 0;
};
Foo::~Foo() {} //pre-C++11
Foo::~Foo() = default; //for an empty body with some benefits; C++11 and on
答案 2 :(得分:0)
如果你根本没有声明析构函数,编译器会生成一个析构函数,但如果你声明一个,它会抑制自动生成,所以你必须定义它,否则你将得到一个未解析的符号错误链接时间。
在C ++ 11中,您可以将析构函数声明为虚拟,但仍然让编译器生成其实现:
virtual ~Foo() = default;
必须以某种方式定义基类的析构函数(即使它是空的),因为派生类的析构函数在结尾隐式调用它。拥有纯虚拟析构函数是没有意义的;派生类可以定义自己的析构函数,但是它们不能定义 base 类的析构函数。