继承之动态内存分配&深拷贝浅拷贝

baseDMA.h

#ifndef BASEDMA_H_
#define BASEDMA_H_
#include <iostream>

//基类
class baseDMA
{
private:
	char *label; //动态内存分配
public:
	baseDMA(const char *l = "null"); //构造函数
	baseDMA(const baseDMA & rs); //复制函数
	virtual ~baseDMA();
	baseDMA & operator = (const baseDMA & rs); //赋值函数
	friend std::ostream & operator<<(std::ostream & os,const baseDMA & ou_ob);
};


//派生类不使用动态内存分配
class lacksDMA:public baseDMA 
{
private:
	char color[100];
public:

	lacksDMA(const char *co = "null",const char *l = "null");
	friend std::ostream & operator<<(std::ostream & os,const lacksDMA & ou_ob);
};

//派生类使用动态内存分配
class hasDMA:public baseDMA 
{
private:
	char *style; //动态内存分配
public:
	hasDMA(const char *l = "null", const char *s = "null"); //构造函数
	hasDMA(const hasDMA & ha);//复制函数
	hasDMA & operator = (const hasDMA & ha);
	virtual ~hasDMA();
	friend std::ostream & operator<<(std::ostream & os,const hasDMA & ou_ob);
};

#endif

baseDMA.cpp

#include "baseDMA.h"


//baseDMA
baseDMA::baseDMA(const char *l)
{
	label = new char[std::strlen(l)+1];
	std::strcpy(label,l);
}

baseDMA::baseDMA(const baseDMA & re) 
{

	this->label = new char[std::strlen(re.label)+1];
	std::strcpy(this->label,re.label);
}

baseDMA::~baseDMA()
{
	std::cout << "来自baseDMA析构函数" << "(地址:" << this <<")\n";
	delete [] this->label;
}

baseDMA & baseDMA::operator=(const baseDMA & rs)
{
	if(this == &rs) //如果是同样的一个相互复制 直接return
	{
		return *this;
	}
	delete [] this->label;
	this->label = new char [std::strlen(rs.label) + 1];
	std::strcpy(this->label,rs.label);
		return *this;
}
std::ostream & operator<<(std::ostream & os,const baseDMA & ou_ob)
{
	os<< "label--->" << ou_ob.label << std::endl;
	return os;
}


//lacksDMA
lacksDMA::lacksDMA(const char *co, const char *l):baseDMA(l)
{
	
	std::strcpy(this->color,co);
}

std::ostream &operator<<(std::ostream & os, const lacksDMA & ou_ob)
{

	os << (baseDMA)ou_ob; //强制装换调用基类的重载输出

	//std::cout << &(baseDMA)ou_ob << std::endl;
	//这里强制转换 编译器会弄出来一个baseDMA的临时变量 并且用baseDMA的析构函数去析构它

	os << "color--->" << ou_ob.color << std::endl;
	return os;
}


//hasDMA
hasDMA::hasDMA(const char *l, const char *s):baseDMA(l)
{
	this->style = new char [std::strlen(s) + 1];
	std::strcpy(this->style,s);
}


hasDMA::hasDMA(const hasDMA & ha):baseDMA(ha) //复制构造函数
{
	this->style = new char [std::strlen(ha.style) + 1];
	std::strcpy(this->style,ha.style);
}


hasDMA & hasDMA::operator = (const hasDMA & ha) //赋值函数 //可以直接使用 基类构造函数吗? 
{
	if(this == &ha)
	{
		return *this;
	}
	//使用基类的赋值构造函数
	baseDMA::operator=(ha);
	delete [] this->style;
	std::strcpy(this->style,ha.style);
	return *this;
}
hasDMA::~hasDMA() //需要显示的调用 基类的析构函数吗? (不需要 编译器会自动调用 手动在这里在调用一次的话会出问题)
{
	
	std::cout << "来自hasDMA析构函数" << "(地址:" << this <<")\n";
	delete [] this->style;
}


std::ostream & operator<<(std::ostream & os,const hasDMA & ou_ob)
{
	os << (baseDMA)ou_ob;
	os << "style--->" << ou_ob.style << std::endl;
	return os;
}
Main.cpp

#include"baseDMA.h"

using std::cout;
void testBaseDestructor()
{
	baseDMA base("这个函数测试baseDMA析构函数生效情况");
	cout << base;
}

void testLacksDestructor()
{  
	lacksDMA lacks("这个函数测试lacksDMA析构函数生效情况","这个函数测试lacksDMA析构函数生效情况");
	cout << lacks;
}

void testhasDestructor()
{
	hasDMA has("这个函数测试hasDMA析构函数生效情况","这个函数测试hasDMA析构函数生效情况");
	cout << has;
}

void testSlightCopy(lacksDMA & f) //测试浅拷贝里面 A对象将值拷给B对象以后 A马上执行析构 B还存在吗? (存在)
{
	lacksDMA temp("hello","hi");
	f = temp; //浅拷贝
}
void main()
{
	cout << "/********测试baseDMA********/\n";
	baseDMA baseOne("hello baseDMA"); //使用构造函数
	cout << baseOne;
	baseDMA baseTwo(baseOne); //使用复制构造函数
	cout << baseTwo;
	baseDMA baseThree("hi baseDMA");
	cout << baseThree;
	baseThree = baseOne; //使用赋值函数
	cout << baseThree;
	testBaseDestructor();

	//输出结果:
	/*label--->hello baseDMA
	label--->hello baseDMA
	label--->hi baseDMA
	label--->hello baseDMA
	label--->这个函数测试baseDMA析构函数生效情况
	来自baseDMA析构函数(地址:0018F600)*/

	cout << "\n\n/********测试lacksDMA********/\n";
	lacksDMA lacksOne("hello lacksDMA' color","hello baseDMA' lable");//使用lacksDMA的构造函数(lacksDMA会调用baseDMA的构造函数)
	cout << lacksOne;
	cout << "\n";
	lacksDMA lacksTwo(lacksOne); //使用lacksDMA的复制构造函数
	cout << lacksTwo;
	cout << "\n";
	lacksDMA lacksThree("hi lacksDMA' color","hi baseDMA' lable");
	cout << lacksThree;
	lacksThree = lacksTwo; //使用lacksDMA的赋值构造函数
	cout << lacksThree;
	cout << "\n";
	testLacksDestructor();

	lacksDMA lacksFour("1","2");
	cout << lacksFour;
	testSlightCopy(lacksFour);
	cout << lacksFour;

	//输出结果:
	/* label--->hello baseDMA' lable
	来自baseDMA析构函数(地址:0018F538)
	color--->hello lacksDMA' color

	label--->hello baseDMA' lable
	来自baseDMA析构函数(地址:0018F538)
	color--->hello lacksDMA' color

	label--->hi baseDMA' lable
	来自baseDMA析构函数(地址:0018F538)
	color--->hi lacksDMA' color
	label--->hello baseDMA' lable
	来自baseDMA析构函数(地址:0018F538)
	color--->hello lacksDMA' color

	label--->这个函数测试lacksDMA析构函数生效情况
	来自baseDMA析构函数(地址:0018F3DC)
	color--->这个函数测试lacksDMA析构函数生效情况
	来自baseDMA析构函数(地址:0018F598) */

	cout << "\n\n/********测试hasDMA********/\n";
	hasDMA hasOne("hello baseDMA' lable","hello baseDMA' style");//使用hasDMA的构造函数
	cout << hasOne;
	cout << "\n";
	hasDMA hasTwo(hasOne); //使用hasDMA的复制构造函数
	cout << hasTwo;
	cout << "\n";
	hasDMA hasThree("hi baseDMA' lable","hi baseDMA' style");
	cout << hasThree;
	cout << "\n";
	hasThree = hasOne;  //使用hasDMA的赋值函数
	cout << hasThree;
	cout << "\n";
	testhasDestructor();
	//输出结果:
	/*label--->hello baseDMA' lable
	来自baseDMA析构函数(地址:0018F538)
	style--->hello baseDMA' style

	label--->hello baseDMA' lable
	来自baseDMA析构函数(地址:0018F538)
	style--->hello baseDMA' style

	label--->hi baseDMA' lable
	来自baseDMA析构函数(地址:0018F538)
	style--->hi baseDMA' style

	label--->hello baseDMA' lable
	来自baseDMA析构函数(地址:0018F538)
	style--->hello baseDMA' style

	label--->这个函数测试hasDMA析构函数生效情况
	来自baseDMA析构函数(地址:0018F440)
	style--->这个函数测试hasDMA析构函数生效情况
	来自hasDMA析构函数(地址:0018F5FC)
	来自baseDMA析构函数(地址:0018F5FC)*/
	system("pause");

}

/*总结:

1,派生类里面没有使用动态内存分配 那么复制构造函数,析构函数和赋值函数都不用重写(用编译器提供的默认潜拷贝就可以了)
	1),默认拷贝遇到char字符串会用strcpy进行复制.
2,派生类里面使用动态内存分配 那么派生来的复制构造函数,析构函数和赋值函数都要重写(如果不重写编译器使用浅拷贝拷贝原对象的地址 那么原对象被析构以后 拷贝它的对象就会出现问题)
3,在派生来的重载<<运算数输出里面,要显示调用基类的重载<<运算符
	1)且调用的时候要将派生类强制转换为基类,
		2)强制转换的时候编译器会弄出来一个临时对象
4,派生类里面使用动态内存分配的时候 析构函数要写为虚函数 派生类里面要重新实现析构函数 析构派生来里面动态分配的变量
	1)(在派生类里面的析构函数不用显示调用基类的析构函数,若调用 将出错)
5,
*/



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值