C++基础(C++Primer学习)

C++基础(十三)
<第十三章—继承与动态内存分配>

问题:继承是怎样与动态内存分配进行互动的,如果基类使用动态内存分配,并重新定义赋值和复制构造函数,对派生类将产生什么影响?

1、创建一个基类:
头文件

#pragma once
#include"list.h" //一些基本的库
class BaseDma
{
private:
	char* label;
	int rating;
public:
	BaseDma(const char* la = NULL, int ra = 0);
	BaseDma(const BaseDma& b);
	virtual ~BaseDma(){}

	BaseDma& operator=(const BaseDma& b);
	friend ostream& operator<<(ostream& os, BaseDma& b);
};

.cpp文件:

#include "Dma.h"

BaseDma::BaseDma(const char* la, int ra)
{
	label = new char[strlen(la)+1];
	strcpy(label, la);
	rating = ra;
}

BaseDma::BaseDma(const BaseDma& b)
{
	label = new char[strlen(b.label) + 1];
	strcpy(label, b.label);
	rating = b.rating;
}

BaseDma::~BaseDma()
{
	delete[]label;
}

BaseDma& BaseDma::operator=(const BaseDma& b)
{
	if (this == &b)
		return *this;
	else
	{
		delete[]label;
		label = new char[strlen(b.label) + 1];
		strcpy(label, b.label);
		rating = b.rating;
		return *this;
	}
}

ostream& operator<<(ostream& os, BaseDma& b)
{
	os << b.label << '\t' << b.rating << endl;
	return os;
}

2、第一种情况:
派生类当中不使用new方法,那么派生类的析构函数可以省略,复制构造函数也可以省略,使用默认的复制构造函数

class NonewDma :public BaseDma
{
	/*默认的复制构造函数执行成员复制,
	这对于动态内存分配是不合适的,
	但是对于没有使用new方法的成员来说是合适的*/
private:
	enum{col_LEN=40};
	char color[col_LEN];
public:
	NonewDma(char*p=NULL,int ra=0,const char*pa="blank");
	NonewDma(BaseDma&b, const char* pa = "blank");
	~NonewDma(){} //可有可无
	friend ostream& operator<<(ostream& os, NonewDma& b);
};

.cpp文件

ostream& operator<<(ostream& os,const BaseDma& b)
{
	os << b.label << '\t' << b.rating << endl;
	return os;
}

NonewDma::NonewDma(char* p, int ra, const char* pa) :BaseDma(p, ra)
{
	strncpy(color, pa, col_LEN - 1);
	color[col_LEN - 1] = '\0';
}

NonewDma::NonewDma(const BaseDma& b, const char* pa) :BaseDma(b)
{
	strncpy(color, pa, col_LEN - 1);
	color[col_LEN - 1] = '\0';
}

ostream& operator<<(ostream& os, const NonewDma& b)
{
	os << (const BaseDma&)b << '\t';
	os << b.color << endl;
	return os;
}

3、第二种情况:派生类也是有new方法
还是上面的基类,再创建一个它的派生类:
头文件:

class HasnewDma :public BaseDma
{
	/*
	该派生类将会使用new方法开辟内存空间
	*/
private:
	char* style;
public:
	HasnewDma(const BaseDma& b, const char* p = NULL);
	HasnewDma(const char* la = NULL, int ra = 0, const char* p = NULL);
	HasnewDma(const HasnewDma& b);
	~HasnewDma();
	HasnewDma& operator=(const HasnewDma& b);

	friend ostream& operator<<(ostream& os, const HasnewDma& b);
};

.cpp文件:

//构造函数
HasnewDma::HasnewDma(const BaseDma& b, const char* p) :BaseDma(b)
{
	style = new char[strlen(p) + 1];
	strcpy(style, p);
}
//构造函数
HasnewDma::HasnewDma(const char* la , int ra, const char* p) : BaseDma(la, ra)
{
	style = new char[strlen(p) + 1];
	strcpy(style, p);
}
//复制构造函数
HasnewDma::HasnewDma(const HasnewDma& b)
{
	style = new char[strlen(b.style) + 1];
	strcpy(style, b.style);
}
//析构函数
HasnewDma::~HasnewDma()
{
	delete[]style;
}
//重载运算符
HasnewDma& HasnewDma::operator=(const HasnewDma& b)
{
	if (this == &b)
		return *this;
	else
	{	
		BaseDma::operator=(b);
		delete[]style;
		style = new char[strlen(b.style) + 1];
		strcpy(style, b.style);
		return *this;
	}
}
//友元函数定义
ostream& operator<<(ostream& os, const HasnewDma& b)
{
	os << (BaseDma&)b << endl;
	os << b.style << endl;
	return os;
}

使用两种派生类:

int main()
{

	BaseDma shirt("lp", 200);
	NonewDma shirt2(shirt, "hello world!");
	HasnewDma shirt1(shirt, "hello world!");
	cout << shirt1 << endl;
	cout << shirt2 << endl;

总结:如果派生类不使用new方法,那么就可以使用默认的复制构造函数和析构函数,如果使用了,就需要自定义复制构造函数和析构函数。当基类和派生类都使用动态内存分配时,派生类的析构函数、复制构造函数、赋值运算符都必须使用相应的基类方法处理基类元素。对于析构函数,这是自动完成的,对于构造函数,这是通过在初始化成员列表中调用基类的复制构造函数来完成的,如果不这样做,将自动调用基类的默认构造函数。对于赋值运算符,这是通过使用作用域解析运算符显式的调用基类的复制运算符来完成的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值