类继承中构造函数和析构函数的调用

定义三个类:

class CA
{
public:
	CA() { cout << "CA constructor" << endl; }
	~CA() { cout << "CA desstructor" << endl; }
};

class CB :public CA
{
public:
	CB() { cout << "CB constructor" << endl; }
	~CB() { cout << "CB desstructor" << endl; }
};

class CC :public CB
{
public:
	CC() { cout << "CC constructor" << endl; }
	~CC() { cout << "CC desstructor" << endl; }
};

情况1:

int main()
{
	CC* p=new CC();
	delete p;
	system("pause");
	return 0;
}

在这里插入图片描述结果1:
情况2:

int main()
{
	CA * p = new CC();
	delete p;
	system("pause");
	return 0;
}

结果2

  • 只调了CA的析构函数,出问题了,这样的话,就会出现基类的构造函数调用了,但是派生类的构造函数没调用,对象的派生部分不会被销毁,这将导致资源泄漏,所以我们在设计一个类的时候,如果类至少拥有一个虚函数,或者说基类被设计用于多态,在这种情况下,一个派生类的对象可能通过一个基类指针来进行操作,然后进行销毁,如果这样的话,那么这个基类的析构函数要设置成虚拟的,有些类虽然是基类,但是不是用于多态的,没有虚函数,没有被设计成允许经由基类接口派生类对象进行操作,那么也无需设成虚析构函数,毕竟增加了开销。 情况3就是增加了虚函数的程序

情况3:加入虚析构函数

#include <iostream>
#include <vector>
using namespace std;
class CA
{
public:
	CA() { cout << "CA constructor" << endl; }
	virtual ~CA() { cout << "CA desstructor" << endl; }
};

class CB :public CA
{
public:
	CB() { cout << "CB constructor" << endl; }
	~CB() { cout << "CB desstructor" << endl; }
};

class CC :public CB
{
public:
	CC() { cout << "CC constructor" << endl; }
	~CC() { cout << "CC desstructor" << endl; }
};
int main()
{
	CA * p = new CC();
	delete p;
	system("pause");
	return 0;
}

在这里插入图片描述
情况4:保存情况3的虚析构函数,修改main函数中的代码

int main()
{
   CB * p = new CC();
   delete p;
   return 0;
}

或者把虚析构函数放到B中,即:

virtual ~CB() { cout << "CB desstructor" << endl; }

结国都是下面的情况

  • 结论:如果是CB指向派生类,只要CB或者其基类中存在虚析构函数,那么也是所有的析构函数都调用的了
    在这里插入图片描述

情况5:

int main()
{
   void * p = new CC();
   delete p;
   return 0;
}

在这里插入图片描述

可以自己敲敲代码 看看其他情况都是什么样的:

总结

如果:
C1 * p = new C2();
delete p;
这样的代码

这里,C1是C2的基类,C1可能是C2的父类,可能是父类的父类,可能是父类的父类的父类,等等----------

那么首先,new的时候调用的构造函数是
从C2的第一个祖先一直到C2………………。和C1 * p 中的C1是什么没关系,只和new后面的有关系

在delete p的时候,那么有以下几种情况:

  1. C1或者C1的祖先(基类)中,含有虚析构函数,那么调用的析构函数的顺序是从C2一直到C2的第一个祖先
    2)如果C1或者C1的祖先中,没有一个是类是含有虚析构函数的,那么调用的是从C1一直到C1(也是C2的)的第一个祖先的
    3)如果C1是void,那就什么析构都不调用了。
    4)如果虚析构函数在C1和C2之间,直接会抛出内存错误也就是说C1是基类CC是C1的子类,C2是CC的子类,
    只有CC的析构函数是虚析函数,则当执行:
	C1 *p=new C2();
	就会出现内存错误:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

如果一个类,作为多态的基类,那么尽量把析构函数声明成虚的

参考博客:加上了自己的一点点理解,有舍有得.
博主:xjbclz
博客地址:https://blog.csdn.net/xjbclz/article/details/51811219

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值