C++ 为什么我们没有义务实现纯虚拟析构函数?

C++ 为什么我们没有义务实现纯虚拟析构函数?,c++,oop,pure-virtual,virtual-destructor,C++,Oop,Pure Virtual,Virtual Destructor,使一个类抽象是通过使它的一个成员函数成为纯虚函数 使类抽象化要求类的子类实现基本的纯虚函数 我们甚至可以将基类析构函数设置为纯的,这就足够抽象类了 问题是: 为什么我们没有义务在派生类中实现纯虚基的析构函数 > P>这是否意味着只要C++在默认情况下添加四个成员函数:构造函数、复制构造函数、赋值和析构函数,我们不需要在派生类中实现它? 例如: #包括 使用名称空间std; 阶级基础 { 公众: Base(){cout 为什么我们没有义务在派生类中实现纯虚基的析构函数 因为析构函数不会被重写

使一个类抽象是通过使它的一个成员函数成为纯虚函数

使类抽象化要求类的子类实现基本的纯虚函数

我们甚至可以将基类析构函数设置为纯的,这就足够抽象类了

问题是:

  • 为什么我们没有义务在派生类中实现纯虚基的析构函数

  • > P>这是否意味着只要C++在默认情况下添加四个成员函数:构造函数、复制构造函数、赋值和析构函数,我们不需要在派生类中实现它?

例如:

#包括
使用名称空间std;
阶级基础
{
公众:
Base(){cout
为什么我们没有义务在派生类中实现纯虚基的析构函数

因为析构函数不会被重写

为了帮助记住这一点,请考虑一下名称:
~Base
~Derived
是不同的。构造函数和析构函数不是通过重写来工作的,而是在一个链中调用的:最底层的析构函数运行,然后调用其父析构函数,父析构函数运行,然后调用其父析构函数,等等

这就是为什么如果要删除某个派生类的实例,即使它被标记为纯虚拟的,也必须为析构函数提供主体:在析构函数链中到达它时需要调用主体

那么,如何处理虚拟析构函数呢?这样做是为了让编译器知道在遇到某个类的销毁时调用最底层的析构函数。所以销毁确实使用虚拟表,只是在派生析构函数完成后运行父类析构函数,所以这不是标准的o维利丁

这是否意味着只要C++在默认情况下添加四个成员函数:构造函数、复制构造函数、赋值和析构函数,我们不需要在派生类中实现它?

我不太理解这个问题,但是在任何情况下,默认添加的方法都不是纯虚拟的,可以在继承链中的每个类中创建

为什么我们没有义务在派生类中实现纯虚基的析构函数

因为析构函数不会被重写

为了帮助记住这一点,请考虑一下名称:
~Base
~Derived
是不同的。构造函数和析构函数不是通过重写来工作的,而是在一个链中调用的:最底层的析构函数运行,然后调用其父析构函数,父析构函数运行,然后调用其父析构函数,等等

这就是为什么如果要删除某个派生类的实例,即使它被标记为纯虚拟的,也必须为析构函数提供主体:在析构函数链中到达它时需要调用主体

那么,如何处理虚拟析构函数呢?这样做是为了让编译器知道在遇到某个类的销毁时调用最底层的析构函数。所以销毁确实使用虚拟表,只是在派生析构函数完成后运行父类析构函数,所以这不是标准的o维利丁

这是否意味着只要C++在默认情况下添加四个成员函数:构造函数、复制构造函数、赋值和析构函数,我们不需要在派生类中实现它?

我不太理解这个问题,但在任何情况下,默认添加的方法都不是纯虚拟创建的,可以在继承链中的每个类中创建。

基本上是因为派生类会自动生成析构函数。但是,通过创建纯虚拟析构函数,您的类会变得抽象,而不是pos可以创建该类型的对象(例如,
new Base;
将不会编译)。这主要是因为为派生类自动生成析构函数。但是,通过创建纯虚拟析构函数,类将变得抽象,并且不可能创建该类型的对象(例如,
newbase;
将不编译)。
#include <iostream>
using namespace std;

class Base
{
    public:
        Base(){cout << "Base Ctor" << endl;}
        virtual ~Base() = 0 {cout << "Virtual base dtor" << endl; }
};

class Derived : public Base
{
    public:
        Derived(){cout << "Derived Ctor" << endl;}
         // virtual ~Derived() {cout << "Virtual Derived dtor" << endl; }
};

int main()
{

    Base* theBase = new Derived;
    delete theBase;

    cout << endl;


    cout << endl << endl;
    return 0;
}