不需要定义基类析构函数?

时间:2014-06-15 15:23:17

标签: c++

在我看到的关于多态的所有例子中,基类的析构函数是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,编译器不允许我这样做。

3 个答案:

答案 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 类的析构函数。