"调用基类指针指向的派生类的非虚的析构函数"是个什么东西?

今天刷QQ,看到群里甩了张这样的表情包

很有意思,看图片可以知道是”tan90°”表情包的衍生版,那么问题来了

“调用基类指针指向的派生类的非虚的析构函数”是个什么东西?

为什么它不可能呢?

首先,我们写出代码

#include<iostream>

using namespace std;

class Base {
public:
    Base() = default;
    ~Base() {
        cout << "delete base" << endl;
    }
};

class Derived :public Base {
public:
    Derived() = default;
    ~Derived() {
        cout << "delete derived" << endl;
    }
};

int main() {
    Base *p = new Derived();
    delete p;
    system("pause");
    return 0;
}

运行结果:

果然没有运行派生类的析构函数

用正确的写法再写一次

#include<iostream>

using namespace std;

class Base {
public:
    Base() = default;
    virtual ~Base() {
        cout << "delete base" << endl;
    }
};

class Derived :public Base {
public:
    Derived() = default;
    virtual ~Derived() {
        cout << "delete derived" << endl;
    }
};

int main() {
    Base *p = new Derived();
    delete p;
    system("pause");
    return 0;
}

运行结果:

这样便正确了

为什么?

  • 一旦某个函数被声明成虚函数,则在所有派生类中它都是虚函数

  • 由于静态绑定,如果以一个基类指针指向一个派生类对象,那么经由该指针只能访问基类定义的函数

  • 如果基类的析构函数不是虚函数,则delete一个指向派生类对象的基类指针将产生未定义的行为

也就是说,要调用基类指针指向的派生类的非虚的析构函数,只能将基类的析构函数定义为非虚的

而通过基类指针,只能访问基类定义的函数,但是基类的析构函数非虚,于是直接执行了,轮不到派生类的析构函数登场

  • 基类的引用或指针调用一个虚成员函数时会执行动态绑定

在正确的写法下,通过基类指针,动态绑定到派生类的虚析构函数上,于是先执行派生类类的析构函数,然后执行基类的析构函数

参考文献

[1]《C++ Primer(第5版)》电子工业出版社——第十五章