C++PrimerPlus(第6版)中文版:Chapter13.7继承和动态内存分配:usedma.cpp

本文探讨了继承与动态内存分配之间的交互作用,特别是在基类使用动态内存分配的情况下,如何影响派生类的设计与实现。文章通过两种不同类型的派生类——使用与未使用动态内存分配的派生类——详细说明了在不同场景下派生类应该如何正确地定义析构函数、复制构造函数和赋值运算符。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

继承是怎样与动态内存分配进行互动的呢?如果基类采用了动态内存分配,并重新定义了赋值和复制构造函数,这将怎样影响派生类的实现呢?这个是取决于派生类的派生类的属性,如果派生类也使用了动态内存分配,那么就有一些技巧需要注意了。

第一种情况:派生类不使用new ,那么就没有必要为派生类定义显式析构函数、复制构造函数、赋值运算符。派生类写成下面这样。。。 就不需要做很多麻烦的事情,它没有使用new。

class lacksDMA:public baseDMA

{
    private:
            char color[40];
    public:
    ........

}

第二种情况:派生类使用了new。

写成这样的派生类:

class hasDMA:public baseDMA

{
    private:
            char *style ;//use new in constructor
    public:
    ........

}

在这种情况下,必须为派生类定义显式析构函数、复制构造函数、赋值运算符。

例子代码如下:

dma.h

#pragma once
#include <iostream>
//Base Class use DMA(动态内存分配)
class baseDMA
{
private:
		char* label;
	    int rating;
public:
	baseDMA(const char * l="null",int r=0);//构造函数
	baseDMA(const baseDMA & rs); //复制构造函数
	virtual ~baseDMA(); //析构函数
	baseDMA& operator=(const baseDMA& rs);//赋值运算符
	friend std::ostream& operator<<(std::ostream & os,const baseDMA & rs);
};
//derived class without DMA 
// no destructor needed
//uses implicit copy constructor
//uses implicit assignment operator
class lacksDMA:public baseDMA
{
public:
	lacksDMA(const char * c="blank",const char * l="null",int r=0);
	lacksDMA(const char * c,const baseDMA & rs);
	friend std::ostream& operator<<(std::ostream & os,const lacksDMA & rs);
private:
	enum {COL_LEN=40};
	char color[COL_LEN];
};
//derived class with DMA
class hasDMA :public baseDMA
{
private:
	char* style;
public:
	hasDMA(const char * s="none",const char * l="null",int r=0);//默认的构造函数
	hasDMA(const char* s,const baseDMA & rs);//拷贝构造函数
	hasDMA(const hasDMA & hs);//拷贝构造函数
	~hasDMA();
	hasDMA& operator=(const hasDMA& hs);
	friend std::ostream& operator<<(std::ostream& os, const hasDMA& rs);
};


dma.cpp

#pragma warning(disable:4996)//这样可以 使得使用std::strcpy() 不报错
#include "dma.h"
#include <cstring>
//baseDMA methods
baseDMA::baseDMA( const char* l, int r)
{
	label = new char[std::strlen(l)+1];
	std::strcpy(label,l);//将l中的内容复制到label中
	//strcpy_s(label, l);//将l中的内容复制到label中
	rating = r;
}
baseDMA::baseDMA(const baseDMA& rs)
{
	label = new char[std::strlen(rs.label)+1];
	std::strcpy(label, rs.label);
	rating = rs.rating;
}
baseDMA::~baseDMA()
{
	delete[] label;
}
baseDMA& baseDMA::operator=(const baseDMA& rs)
{
	if (this == &rs)
		return *this;
	delete[] label;
	label = new char[std::strlen(rs.label) + 1];
	std::strcpy(label, rs.label);
	rating = rs.rating;
	return *this;
}
std::ostream& operator<<(std::ostream& os, const baseDMA& rs)
{
	os << "Label: " << rs.label << std::endl;
	os << "Rating: " << rs.rating << std::endl;
	return os;
}
//lackDMA methods lacksDMA 比基类多了两个私有成员 enum {COL_LEN=40} 和char color[COL_LEN]
lacksDMA::lacksDMA(const char* c, const char* l, int r) :baseDMA(l, r)
{
	std::strncpy(color,c,39);
	color[39] = '\0';//这是最后一个元素
}
lacksDMA::lacksDMA(const char* c, const baseDMA& rs):baseDMA(rs)
{
	std::strncpy(color,c,COL_LEN-1);//拷贝一定数量的字符串到前面的字符串
	color[COL_LEN - 1] = '\0';
}
std::ostream & operator<<(std::ostream& os, const lacksDMA & ls)
{
	os << (const baseDMA &)ls;
	os << "Color: " << ls.color << std::endl;
	return os;
}
//hasDMA methods  该类比基类多了一个 char * style
hasDMA::hasDMA(const char* s, const char* l, int r):baseDMA(l,r)
{
	style = new char[std::strlen(s) + 1];
	std::strcpy(style,s);
}
hasDMA::hasDMA(const char* s, const baseDMA & rs) : baseDMA(rs)
{
	style = new char[std::strlen(s) + 1];
	std::strcpy(style, s);
}
hasDMA::hasDMA(const hasDMA& hs):baseDMA(hs)//invoke base class copy constructor 调用基类的拷贝构造函数
{
	style = new char[std::strlen(hs.style)+1];
	std::strcpy(style, hs.style);
}
hasDMA::~hasDMA()
{
	delete[] style;
}
hasDMA& hasDMA::operator=(const hasDMA& hs)
{
	if (this == &hs)
		return *this;
	baseDMA::operator=(hs);//copy base portion 拷贝基类的部分
	delete[] style;//prepare for the new style ;
	style = new char[std::strlen(hs.style)+1];
	std::strcpy(style,hs.style);
	return *this;
}
std::ostream& operator<<(std::ostream& os, const hasDMA& hs)
{
	// type cast to match operator <<(ostream & ,const baseDMA &) 这里做了一个强制转换,转换为父类
	os << (const baseDMA &)hs;
	os << "Style: " << hs.style << std::endl;
	return os;
}


主函数就是使用了上面声明的类,然后做了个输出。

usedma.cpp

// Chapter13.7InheritenceAndDMA_usedma.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include "dma.h"

int main()
{
   // std::cout << "Hello World!\n";
	using std::cout;
	using std::endl;

	baseDMA shirt("Portabelly",8);

	lacksDMA balloon("red","Blimpo",4);

	hasDMA map("Mercator","Buffalo Keys",5);

	cout << "Displaying BaseDMA object:\n";
	cout << shirt << endl;

	cout << "Displaying lacksDMA object:\n";
	cout << balloon << endl;

	cout << "Displaying hasDMA object:\n";
	cout << map << endl;

	lacksDMA balloon2(balloon);
	cout << "Result of lacksDMA copy:\n";
	cout << balloon2 << endl;

	hasDMA map2;
	map2 = map;
	cout << "Result of hasDMA assignment:\n";
	cout << map2 << endl;
	return 0;


}


运行结果略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值