1、为什么声明基类析构函数为虚函数?
(1)基类指针 指向 基类对象:不用考虑基类析构函数是否声明为虚函数。
(2)基类指针 指向 派生类对象:若基类析构函数不为虚函数,在delete基类指针时,只会调用基类的析构函数,不会调用派生类的析构函数(资源未释放,基类无法操作派生类中非继承的成员),进而可能导致内存泄漏。
2、如下代码示例
#include<iostream>
using namespace std;
//基类A
class classA
{
public:
classA(){ cout << "Construct in classA" << endl; };
~classA(){ cout << "Destruct in classA" << endl; };
void print(){ cout << "Print classA" << endl; };
};
//派生类B
class classB : public classA
{
public:
classB(){ cout << "Construct in classB" << endl; };
~classB(){ cout << "Destruct in classB" << endl; };
void print(){ cout << "Print classB" << endl; };
};
//基类C
class classC
{
public:
classC(){ cout << "Construct in classC" << endl; };
//虚析构函数
virtual ~classC(){ cout << "Destruct in classC" << endl; };
//虚成员函数
virtual void print(){ cout << "Print classC" << endl; };
};
//派生类D
class classD : public classC
{
public:
classD(){ cout << "Construct in classD" << endl; };
//以下两个函数可不加virtual关键字修饰,由于函数重写编译时会默认加上(基类C中为虚函数)
//析构函数比较特殊,编译时名字一样,因此也构成函数重写
virtual ~classD(){ cout << "Destruct in classD" << endl; };
virtual void print(){ cout << "Print classD" << endl; };
};
int main()
{
cout << "------------part 1------------" << endl;
classB *ptrB = new classB;//派生类指针指向派生类对象
ptrB->print();
delete ptrB;
cout << endl << "------------part 2------------" << endl;
classA *ptrA = new classB;//基类指针指向派生类对象(基类非虚析构)
ptrA->print();
delete ptrA;
cout << endl << "------------part 3------------" << endl;
classC *ptrC = new classD;//基类指针指向派生类对象(基类虚析构)
ptrC->print();
delete ptrC;
cout << endl << "------------part 4------------" << endl;
classC *ptrC1 = new classC;//基类指针指向基类对象
ptrC1 ->print();
delete ptrC1 ;
getchar();
return 0;
}
3、执行结果及分析
(1)执行结果
(2)分析
①part 1:派生类对象创建与销毁时,构造及析构函数的调用顺序为,基类构造→派生类构造→派生类析构→基类析构。
②part 2:基类A析构函数不为虚函数,delete基类指针时,未调用派生类B析构函数(非多态,根据指针类型调用)。
③part 3:与part 2对比(上图中红色标记),基类C中析构函数为虚函数,此时形成多态(与类型无关,只与对象有关),delete基类指针时,先调用派生类的析构函数,后调用基类的析构函数。
④part 4:与part 3对比(Print函数输出),基类指针指向基类对象时,调用基类的成员函数;指向派生类对象时,调用派生类的成员函数。这便是多态(动态绑定),在程序执行过程中,动态决定调用哪个函数。
4、多态介绍
多态(动态绑定)的核心是虚函数、虚表、虚表指针,此处推荐一篇头条上的文章《C++ 虚函数表剖析》,链接:C++ 虚函数表剖析。