C++的类中,构造函数用于初始化对象及相关操作,构造函数是不能声明为虚函数的,因为在执行构造函数前对象尚未完成创建,虚函数表还不存在。
而在C++多态中,当用基类指针指向派生类对象时,如果父类析构函数不是虚函数,则在析构时,不会调用到派生类的析构函数。
虚析构函数就是为了解决这样的一个问题:基类的指针指向派生类对象,并用基类的指针删除派生类对象。
之所以可以这样是因为虚析构函数会被记录在虚函数表中,如果派生类继承了基类,则派生类的析构函数也会隐式成为虚函数,并且会替换掉父类的析构函数指针。
#include <iostream>
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 <iostream>
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 <iostream>
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 析构
参考
版权声明:本文为u010275850原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。