C++中子类基类的构造函数和析构函数的调用

构造函数

C++中通常用构造函数来对对象中的数据成员进行初始化,构造函数与类名同名。构造函数没有返回值,只对对象进行初始化。在建立对象时自动调用构造函数,每建立一个对象就调用一次构造函数。

析构函数

析构函数的作用与构造函数相反。名字也与类名相同,只是在类名前加一个“~”符号。当对象的生命周期结束时,释放对象前自动调用析构函数。
静态局部变量在main函数结束时或者调用exit()函数结束程序时,才调用static局部对象的析构函数。
全局对象,在程序的流程离开作用域时,调用全局对象的析构函数。
用new运算符创建的对象,在用delete运算符释放该对象时,先调用该对象的析构函数。
析构函数的作用不是删除对象,而是在撤销对象占用的内存之前完成一些清理工作。不能被重载,一个类中只能有一个析构函数。

构造函数与析构函数的调用次序

析构函数的调用顺序与构造函数相反,最先被调用的构造函数最后调用它的析构函数,最后被调用的构造函数先调用它的析构函数。
1)全局对象的构造函数在本文件模块中的所有函数执行之前被调用。若一个程序包含多个文件,而在这些不同的文件中都定义了全局对象,则这些对象的构造函数的执行顺序不确定。当main函数执行完或者调用exit函数时,调用析构函数。
2)局部对象在建立对象时调用构造函数。若对象所在的函数被调用多次,则在每次建立对象时都会调用构造函数。函数调用结束、对象释放前先调用析构函数。
3)静态局部对象只在程序第一次调用此函数,定义对象时调用构造函数,函数调用结束对象不释放,不调用析构函数。在main函数结束或调用exit函数时调用析构函数。

派生类的构造函数与析构函数

基类的构造函数只对基类的数据成员进行初始化,派生类的构造函数只对派生类新增的数据成员进行初始化,同时也会调用基类的构造函数。
用派生类建立一个对象时,执行构造函数的顺序是:先调用基类的构造函数,再执行派生类构造函数本身。
释放对象时,执行析构函数的顺序是:先调用子类的析构函数,再调用基类的析构函数
定义基类:

class A
{
public:
	A()
	{
		cout << "AA" << endl;
	}
	~A()
	{
		cout << "~AA" << endl;
	}
};

定义子类:

class B :public A
{
public:
	B()
	{
		cout << "BB" << endl;
	}
	~B()
	{
		cout << "~BB" << endl;
	}
};

建立基类对象,调用基类的构造函数:

A* pA = new A();//输出AA

释放基类对象,调用基类的析构函数:

delete pA; //输出~AA

建立子类对象,先调用基类的构造函数,再执行子类的构造函数

B* pB = new B();//先调用基类的构造函数,输出AA,再调用子类的构造函数,输出BB

释放子类对象,先调用子类的析构函数,再调用基类的析构函数

delete pB;  //先调用子类的析构函数,输出~BB,再调用基类的析构函数,输出~AA

main函数:

int main()
{
	A* pA = new A();//输出AA
	delete pA; //输出~AA
	B* pB = new B();//
	delete pB; 
	return 0;
}

执行结果:
C++中子类基类的构造函数和析构函数的调用_第1张图片
基类指针指向子类对象,先调用基类的构造函数,再执行子类构造函数

pA = new B();//先调用基类的构造函数输出AA,再调用子类的构造函数,输出BB

释放指针,这里只调用了基类的析构函数,子类的析构函数并没有调用。按理说是要调用子类的析构函数的,那么这就有问题了。该怎么解决呢?就是在基类中定义虚析构函数

 delete pA;  //输出~AA

在基类中定义虚析构函数

class A
{
public:
	A()
	{
		cout << "AA" << endl;
	}
	virtual ~A()
	{
		cout << "~AA" << endl;
	}
};

子类

class B :public A
{
public:
	B()
	{
		cout << "BB" << endl;
	}
	~B()
	{
		cout << "~BB" << endl;
	}
};

将基类指针指向子类对象,释放基类指针时,就会先调用子类的析构函数,再调用基类的析构函数。

int main()
{
	A* pA = new A();//输出AA
	  pA = new B();//基类指针指向子类对象,先调用基类的构造函数输出AA,再调用子类的构造函数,输出BB
	 delete pA;  
	 return 0;
}

此时的执行结果为:
C++中子类基类的构造函数和析构函数的调用_第2张图片

你可能感兴趣的:(C++,C++,构造函数,析构函数,基类与派生类)