C++中继承 构造函数 析构函数

1.首先要明确的是:C++继承的时候,派生类中包含整个完整的基类子对象。但是在派生类中,有一些方法应该不是一般的继承,比如 构造、析构、拷贝构造...(就是那些在用户未定义时,由系统自动生成默认方法的那些成员方法)这些方法应该是 逐级调用的关系,而不是 “继承” 关系 ... 子类有自己的构造和析构函数

以下代码作为佐证:

// extend_test.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"
#include <iostream>
using namespace std;

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;}
};

int _tmain(int argc, _TCHAR* argv[])
{
	CC *p = new CC() ;
	delete p;
	return 0;
}


程序的运行结果为:

CA constructor
CB constructor
CC constructor
CC desstructor
CB desstructor
CA desstructor
请按任意键继续. . .


2.对以上述代码,如果我们修改main函数如下:

int _tmain(int argc, _TCHAR* argv[])
{
	CA *p = new CC() ;
	delete p;
	return 0;
}

其他不变的话,运行结果如下:

CA constructor
CB constructor
CC constructor
CA desstructor
请按任意键继续. . .

可以看到出问题了,只调用了CA的析构函数,CB和CC都没有调用,如果改成如下:

int _tmain(int argc, _TCHAR* argv[])
{
	CB *p = new CC() ;
	delete p;
	return 0;
}
可以发现结果为:

CA constructor
CB constructor
CC constructor

CB desstructor
CA desstructor
请按任意键继续. . .


如果我们修改基类CA如下:

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

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

运行则会发现,结果又对了

CA constructor
CB constructor
CC constructor
CC desstructor
CB desstructor
CA desstructor
请按任意键继续. . .

我们有如下结论:

当基类的析构函数是虚析构函数,是根据指针的类型调用析构函数;
当积累的析构函数不是虚析构函数时,是根据指针指向对象的类型调用析构函数。
我们在设计一个类的时候,如果类至少拥有一个虚函数,或者说基类被设计用于多态,在这种情况下,一个派生类的对象可能通过一个基类指针来进行操作,然后进行销毁,如果这样的话,那么这个基类的析构函数要设置成虚的,有些类虽然是基类,但是不是用于多态的,没有虚函数,没有被设计成允许经由基类接口派生类对象进行操作,那么也无需设成虚析构函数,毕竟增加了开销。


3.如果我们将代码修改如下:

// extend_test.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"
#include <iostream>
using namespace std;

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

	 ~CA(){cout<<"CA desstructor"<<endl;}
};

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

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

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

	~CC(){cout<<"CC desstructor"<<endl;}
};

int _tmain(int argc, _TCHAR* argv[])
{
	CA *p = new CC() ;
	delete p;
	return 0;
}

运行时会报内存错误:即CA的析构函数不是虚的,而CB或者CC的析构函数是虚拟的,那么在调用delete p;会出现内存错误Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)  

_BLOCK_TYPE_IS_VALID是用来检测内存有效性宏中的一个,这个错误说明指针使用出现了

是因为继承类中出现了虚函数,所以多了一个指向虚函数表的指针,而基类中没有虚函数,所以没有这个指针
所以delete的时候出现了内存错

为了验证他我们修改代码如下:

// extend_test.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"
#include <iostream>
using namespace std;

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

	 ~CA(){cout<<"CA desstructor"<<endl;}

	 virtual void test() {

	 }
};

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

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

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

	~CC(){cout<<"CC desstructor"<<endl;}
};

int _tmain(int argc, _TCHAR* argv[])
{
	CA *p = new CC() ;
	delete p;
	return 0;
}


即加入一个空的无关虚函数,运行无错。


3.如果我们修改代码如下:

// extend_test.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"
#include <iostream>
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 _tmain(int argc, _TCHAR* argv[])
{
	void *p = new CC() ;
	delete p;
	return 0;
}

运行结果为:

CA constructor
CB constructor
CC constructor
请按任意键继续. . .

一个析构函数没有调用.


如果*p是void,那就什么析构都不调用了。


本文到这里就结束了,重要的是记住,在实现多态时,应该将基类的析构函数设为虚函数。


本人为初学者,如有不对,还请指教。

参考:http://wxdlut.blog.163.com/blog/static/12877015820107105119657/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值