虚析构函数和纯虚析构函数

C++的类中,构造函数用于初始化对象及相关操作,构造函数是不能声明为虚函数的,因为在执行构造函数前对象尚未完成创建,虚函数表还不存在。

而在C++多态中,当用基类指针指向派生类对象时,如果父类析构函数不是虚函数,则在析构时,不会调用到派生类的析构函数。

虚析构函数就是为了解决这样的一个问题:基类的指针指向派生类对象,并用基类的指针删除派生类对象。之所以可以这样是因为虚析构函数会被记录在虚函数表中,如果派生类继承了基类,则派生类的析构函数也会隐式成为虚函数,并且会替换掉父类的析构函数指针。

#include 

using namespace std;

class Base
{
public:
    Base() { cout << "in base 构造" << endl; }
    ~Base() { cout << "in base 析构" << endl; }
};

class Child : public Base
{
public:
    Child() { cout << "in child 构造" << endl; }
    ~Child() { cout << "in child 析构" << endl; }
};

class GrandChild : public Child
{
public:
    GrandChild() { cout << "in GrandChild 构造" << endl; }
    ~GrandChild() { cout << "in GrandChild 析构" << endl; }
};

int main()
{
    Base *b = new GrandChild;
    delete b;
    return 0;
}

输出如下:

in base 构造
in child 构造
in GrandChild 构造
in base 析构

如果基类是虚析构函数

#include 

using namespace std;

class Base
{
public:
    Base() { cout << "in base 构造" << endl; }
    virtual ~Base() { cout << "in base 析构" << endl; }
};

class Child : public Base
{
public:
    Child() { cout << "in child 构造" << endl; }
    ~Child() { cout << "in child 析构" << endl; }
};

class GrandChild : public Child
{
public:
    GrandChild() { cout << "in GrandChild 构造" << endl; }
    ~GrandChild() { cout << "in GrandChild 析构" << endl; }
};

int main()
{
    Base *b = new GrandChild;
    delete b;
    return 0;
}

输出如下:

in base 构造
in child 构造
in GrandChild 构造
in GrandChild 析构
in child 析构
in base 析构

此处我们也可以把析构函数声明为纯虚函数,此时必须得有其实现定义且必须定义在类的外部(类内部会造成语法错误)。

这个定义是必须的,因为虚析构函数工作的方式是:最底层的派生类的析构函数最先被调用,然后各个基类的析构函数被调用。也就是说,即使是抽象类,编译器也要调用其析构函数,所以要保证为它提供函数体。如果不这么做,链接时会提示undefined reference to ‘Base::~Base()’ 错误。

基类是纯虚析构函数

#include 

using namespace std;

class Base
{
public:
    Base() { cout << "in base 构造" << endl; }
    virtual ~Base() = 0;
};

Base::~Base() { cout << "in base 析构" << endl; }

class Child : public Base
{
public:
    Child() { cout << "in child 构造" << endl; }
    ~Child() { cout << "in child 析构" << endl; }
};

class GrandChild : public Child
{
public:
    GrandChild() { cout << "in GrandChild 构造" << endl; }
    ~GrandChild() { cout << "in GrandChild 析构" << endl; }
};

int main()
{
    Base *b = new GrandChild;
    delete b;
    return 0;
}

output:

in base 构造
in child 构造
in GrandChild 构造
in GrandChild 析构
in child 析构
in base 析构

参考

x64程序C++打印虚函数表

你可能感兴趣的:(C/C++,Learn,c++,虚析构函数,多态)