C++ 构造函数和析构函数的调用顺序、虚析构函数的作用

构造函数和析构函数的调用顺序

构造函数的调用顺序:

当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的构造函数,依次类推,直至到达最底层的目标派生类的构造函数为止。

析构函数的调用书序:

当删除一个对象时,首先调用该派生类的析构函数,然后调用上一层基类的析构函数,依次类推,直到到达最顶层的基类的析构函数为止。

简单的说,构造函数是“自上向下”调用,析构函数是“自下而上”调用。

演示代码如下:

#include<iostream>
using namespace std;

class Base{
public:
	Base(){cout<<"创建Base基类。"<<endl;}
	~Base() {cout<<"删除Base基类。"<<endl;}
};
class Child : public Base{
public:
	Child() {cout<<"创建Child派生类。"<<endl;}
	~Child() {cout<<"删除Child派生类。"<<endl;} 
};

int main()
{
	cout<<"*********构造函数调用顺序示例***********"<<endl;
	Child *C1 = new Child;
	cout<<"*********析构函数调用顺序示例***********"<<endl;
	delete C1;
}
运行结果如下图:



虚析构函数的作用

通过基类的指针来删除派生类的对象时,基类的析构函数应该是虚的。

原因:在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员。如果想要用基类对非继承成员进行操作,则要把基类的这个操作(函数)定义为虚函数。析构函数同样需要如此。

如果用基类的指针来删除派生类的对象,而这个基类有一个非虚的析构函数,则结果是未定义的。后果是对象的派生部分不会被销毁,然而,基类部分很可能已被销毁,这就导致产生了“部分析构”的情况,这是一个内存泄露

可以通过如下代码来说明:

#include<iostream>
using namespace std;

class Base{
public:
	Base(){cout<<"创建Base基类。"<<endl;}
	~Base() {cout<<"删除Base基类。"<<endl;}	/*非虚析构函数*/
};
class Child : public Base{
public:
	Child() {cout<<"创建Child派生类。"<<endl;}
	~Child() {cout<<"删除Child派生类。"<<endl;} 
};

int main()
{
	cout<<"*********非虚析构函数调用示例***********"<<endl;
	Base *C1 = new Child;
	delete C1;
}
运行结果如下,此时删除C1指针时,只调用了Base类的析构函数,没有调用Child类的析构函数。


当更改Base基类的析构函数为虚函数时,代码如下:

#include<iostream>
using namespace std;

class Base{
public:
	Base(){cout<<"创建Base基类。"<<endl;}
	virtual ~Base() {cout<<"删除Base基类。"<<endl;}	/*虚析构函数*/
};
class Child : public Base{
public:
	Child() {cout<<"创建Child派生类。"<<endl;}
	~Child() {cout<<"删除Child派生类。"<<endl;} 
};

int main()
{
	cout<<"*********虚析构函数调用示例***********"<<endl;
	Base *C1 = new Child;
	delete C1;
}
此时运行结果如下,先调用了Child派生类的析构函数,再调用了Base基类的析构函数。



但是,一般如果不做基类的类的析构函数一般不声明为虚函数,因为虚函数的实现要求对象携带额外的信息,这些信息用于在运行时确定该对象应该调用哪一个虚函数。典型情况下,这一信息具有一种被称为 vptr(virtual table pointer,虚函数表指针)的指针的形式。vptr 指向一个被称为 vtbl(virtual table,虚函数表)的函数指针数组,每一个包含虚函数的类都关联到 vtbl。当一个对象调用了虚函数,实际的被调用函数通过下面的步骤确定:找到对象的 vptr 指向的 vtbl,然后在 vtbl 中寻找合适的函数指针。这样子会使类所占用的内存增加。


原文地址:https://www.cnblogs.com/fengty90/p/3768848.html