C++ Primer Plus 第十三章习题答案+收获

本文介绍了C++中不同类的设计与实现,包括基类Cd及其派生类Classic,展示了如何使用构造函数、析构函数、复制构造函数和赋值运算符。后续章节探讨了使用动态内存分配、纯虚函数和多态性的经典案例。

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

目录

13.1

13.2

13.3

13.4


13.1

//class.h

#pragma once

#ifndef _CLASS_H_
#define _CLASS_H_

//基类
class Cd
{
private:
	char performance[50];
	char label[20];
	int selections;
	double payment;
public:
	Cd(const char* s1="none", const char* s2="none", int n=0, double x=0); //自定义的构造函数的所有参数均为默认参数时则无需再自定义一个默认构造函数
	//Cd(const Cd& d); 没有使用new开辟动态内存空间,类默认的复制构造函数便可以完成任务
	//~Cd(); 析构函数同理
	//Cd & operator=(const Cd&d); 重载赋值运算符同理
	virtual void Report()const; //在派生类中重新定义,需使用虚函数来完成多态
};

class Classic :public Cd
{
private:
	//属于派生类的数据
	char essential[50];
public:
	Classic(const char* s = "none", const char* s1 = "none", const char* s2 = "none", int n = 0, double x = 0);
	//自定义的构造函数的所有参数均为默认参数时则无需再自定义一个默认构造函数
	virtual void Report()const;
};

#endif

//fuc.cpp

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

#pragma warning(disable:4996);

Cd::Cd(const char* s1, const char* s2, int n, double x)
{
	strcpy(performance, s1);
	strcpy(label, s2);
	selections = n;
	payment = x;
}

void Cd::Report()const
{
	cout << "Performance: " << performance << endl;
	cout << "Label: " << label << endl;
	cout << "Selections: " << selections << endl;
	cout << "Payment: " << payment << endl;
}

Classic::Classic(const char* s, const char* s1, const char* s2, int n, double x) :Cd(s1, s2, n, x) //通过成员初始化先创建基类对象
{
	strcpy(essential, s);
}

void Classic::Report()const
{
	Cd::Report(); //基类部分的report(调用基类的Report()函数)
	cout << "Essential: " << essential << endl; //派生类部分的report
}

//main.cpp

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

void Bravo(const Cd& disk);

int main()
{
	Cd c1("Beatles", "Capitol", 14, 35.5);
	Classic c2 = Classic("Piano Sonata in B flat,Fantasia in C", "Alfred Brendel", "Philips", 2, 57.17);
	Cd* pcd = &c1;

	cout << "Using object directl: " << endl;
	c1.Report();
	c2.Report();

	cout << "Using type cd * pointer to objects: " << endl;
	pcd->Report();
	pcd = &c2;
	pcd->Report();

	cout << "Calling a fuction with a Cd reference argument: " << endl;
	Bravo(c1);
	Bravo(c2);

	cout << "Testing assignment:  " << endl;
	Classic copy;
	copy = c2;
	copy.Report();


	system("pause");
	return 0;
}



void Bravo(const Cd& disk) //参数为基类引用,实参可以为基类对象或者派生类对象
{
	disk.Report();
}

13.2

//class.h

#pragma once

#ifndef _CLASS_H_
#define _CLASS_H_


//使用动态内存分配来记录字符串(则需要自定义析构函数,复制构造函数,重载赋值运算符)
//基类
class Cd
{
private:
	char *performance;
	char * label;
	int selections;
	double payment;
public:
	Cd(const char* s1 = "none", const char* s2 = "none", int n = 0, double x = 0); //自定义的构造函数的所有参数均为默认参数时则无需再自定义一个默认构造函数
	Cd(const Cd& d);
	virtual ~Cd(); 
	Cd & operator=(const Cd&d);
	virtual void Report()const; //在派生类中重新定义,需使用虚函数来完成多态
};

class Classic :public Cd
{
private:
	//属于派生类的数据
	char *essential;
public:
	Classic(const char* s = "none", const char* s1 = "none", const char* s2 = "none", int n = 0, double x = 0);
	//自定义的构造函数的所有参数均为默认参数时则无需再自定义一个默认构造函数
	Classic(const Classic& cl);
	~Classic();
	Classic& operator=(const Classic& cl);
	virtual void Report()const;
};



#endif

//fuc.cpp

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

#pragma warning(disable:4996)

//base class
Cd::Cd(const char* s1, const char* s2 , int n, double x) //自定义的构造函数的所有参数均为默认参数时则无需再自定义一个默认构造函数
{
	performance = new char[strlen(s1) + 1];
	strcpy(performance, s1);
	label = new char[strlen(s2) + 1];
	strcpy(label, s2);
	selections = n;
	payment = x;
}

Cd::Cd(const Cd& d)
{
	//深度复制
	performance = new char[strlen(d.performance) + 1];
	strcpy(performance, d.performance);
	label = new char[strlen(d.label) + 1];
	strcpy(label, d.label);
	selections = d.selections;
	payment = d.payment;
}

Cd::~Cd()
{
	delete[]performance;
	delete[]label;
}

Cd& Cd::operator=(const Cd& d)
{
	delete[]performance;
	performance = new char[strlen(d.performance) + 1];
	strcpy(performance, d.performance);
	delete[]label;
	label = new char[strlen(d.label) + 1];
	strcpy(label, d.label);
	selections = d.selections;
	payment = d.payment;
	return *this;
}

void Cd::Report()const //在派生类中重新定义,需使用虚函数来完成多态
{
	cout << "Performance:" << performance << endl;
	cout << "Label: " << label << endl;
	cout << "Selections: " << selections << endl;
	cout << "Payment: " << payment << endl;
}

//derived class
Classic::Classic(const char*s,const char* s1, const char* s2 , int n, double x):Cd(s1,s2,n,x)
{
	essential = new char[strlen(s) + 1];
	strcpy(essential, s);
}

//自定义的构造函数的所有参数均为默认参数时则无需再自定义一个默认构造函数
Classic::Classic(const Classic& cl) :Cd(cl)
{
	essential = new char[strlen(cl.essential) + 1];
	strcpy(essential, cl.essential);
}

Classic::~Classic()
{
	delete[]essential;
}

Classic& Classic::operator=(const Classic& cl)
{
	Cd::operator=(cl); //调用基类的重载赋值运算符,来完成基类部分数据的赋值
	delete[]essential;
	essential = new char[strlen(cl.essential) + 1];
	strcpy(essential, cl.essential);
	return *this;
}

void Classic::Report()const
{
	Cd::Report();
	cout << "Essential: " << essential << endl;
}

//main.cpp

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

void Bravo(const Cd& disk);

int main()
{
	Cd c1("Beatles", "Capitol", 14, 35.5);
	Classic c2 = Classic("Piano Sonata in B flat,Fantasia in C", "Alfred Brendel", "Philips", 2, 57.17);
	Cd* pcd = &c1;

	cout << "Using object directl: " << endl;
	c1.Report();
	c2.Report();

	cout << "Using type cd * pointer to objects: " << endl;
	pcd->Report();
	pcd = &c2;
	pcd->Report();

	cout << "Calling a fuction with a Cd reference argument: " << endl;
	Bravo(c1);
	Bravo(c2);

	cout << "Testing assignment:  " << endl;
	Classic copy;
	copy = c2;
	copy.Report();


	system("pause");
	return 0;
}



void Bravo(const Cd& disk) //参数为基类引用,实参可以为基类对象或者派生类对象
{
	disk.Report();
}

13.3

//class.h
//修改base,lacks,has三个类,让三个类都从一个ABC派生而来( ABC抽象基类(包含纯虚函数,无法创建对象) -> 派生类)

#pragma once

#include<iostream>
using namespace std;

#ifndef _CLASS_H_
#define _CLASS_H_

//ABC抽象基类
class ABC
{
private:
	char* label;
	int rating;
public:
	ABC(const char* s1, int n);
	ABC(const ABC& abc);
	virtual ~ABC(); //基类的虚构函数设置为虚函数
	ABC& operator=(const ABC& abc);
	virtual void View() = 0; //纯虚函数 -- 抽象基类
};

//BaseDMA
class BaseDMA :public ABC
{
private:

public:
	BaseDMA(const char* s1, int n);
	//此派生类中没有动态分配内存,无需自定义复制构造函数,析构函数,重载赋值运算符
	//BaseDMA(const BaseDMA& bd);   
	//~BaseDMA();
	//BaseDMA& operator=(const BaseDMA& bd);
	virtual void View();
};

//LacksDMA
class LacksDMA:public ABC
{
private:
	const static int COL_LEN = 40;
	char color[COL_LEN];
public:
	LacksDMA(const char* s, const char* s1, int n);
	virtual void View();
};

//HasDMA
class HasDMA:public ABC
{
private:
	char* style;
public:
	HasDMA(char* s, char* s1, int n);
	HasDMA(HasDMA& hd);
	~HasDMA();
	HasDMA& operator=(const HasDMA& hd);
	virtual void View();
};




#endif

//fuc.cpp

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

#pragma warning(disable:4996)

//ABC

ABC::ABC(const char* s1, int n)
{
	label = new char[strlen(s1) + 1];
	strcpy(label, s1);
	rating = n;
}
ABC::ABC(const ABC& abc)
{
	label = new char[strlen(abc.label) + 1];
	strcpy(label, abc.label);
	rating = abc.rating;
}

ABC::~ABC() //基类的虚构函数设置为虚函数
{
	delete[]label;
}

ABC& ABC::operator=(const ABC& abc)
{
	delete[]label;
	label = new char[strlen(abc.label) + 1];
	strcpy(label, abc.label);
	rating = abc.rating;
	return *this;
}
void ABC::View() //纯虚函数 -- 抽象基类
{
	cout << "Label: " << label << endl;
	cout << "Rating: " << rating << endl;
}

//BASE
BaseDMA::BaseDMA(const char* s1, int n) :ABC(s1, n)
{
	//BaseDMA无额外的数据成员,所以只需要调用基类的构造函数即可
}

void BaseDMA::View()
{
	cout << "The type is BaseDMA" << endl;
	ABC::View();
}

//LACKS
LacksDMA::LacksDMA(const char* s, const char* s1, int n) :ABC(s1, n)
{
	strcpy(color, s);
}

void LacksDMA::View()
{
	cout << "The type is LacksDMA" << endl;
	ABC::View();
	cout << "Color: " << color << endl;
}

//HAS
HasDMA::HasDMA(char* s, char* s1, int n):ABC(s1,n)
{
	style = new char[strlen(s) + 1];
	strcpy(style, s);
}

HasDMA::HasDMA(HasDMA& hd) :ABC(hd)
{
	style = new char[strlen(hd.style) + 1];
	strcpy(style, hd.style);
}

HasDMA::~HasDMA()
{
	delete[] style;
}

HasDMA& HasDMA::operator=(const HasDMA& hd)
{
	ABC::operator=(hd); //调用基类的重载赋值运算符来对基类数据进行赋值
	delete[] style;
	style = new char[strlen(hd.style) + 1];
	strcpy(style, hd.style);
	return *this;
}

void HasDMA::View()
{
	cout << "The type is HasDMA" << endl;
	ABC::View();
	cout << "Style: " << style << endl;
}

//main.cpp

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


int main()
{
	//包含纯虚函数的基类不能创建对象,但可以创建基类的指针,指向派生类
	ABC* points[3];
	int selection;
	int i = 0;
	char label[50];
	int rating;
	char color[50];
	char style[50];	
	cout << "1----BaseDMA" << endl;
	cout << "2----LacksDMA" << endl;
	cout << "3----HasDMA" << endl;
	while (i < 3)
	{
		//指针必须要通过new来分配相应的内存,声明一个指针并不会给其分配内存
		cout << "Please enter your choice: ";
		cin >> selection;
		if (selection == 1)
		{
			cout << "Please enter the label: " << endl;
			cin >> label;
			cout << "Please enter the rating: " << endl;
			cin >> rating;
			points[i] = new BaseDMA(label, rating); // 在最后加上()直接利用相应构造函数进行初始化 
		}
		else if (selection == 2)
		{
			cout << "Please enter the label: " << endl;
			cin >> label;
			cout << "Please enter the rating: " << endl;
			cin >> rating;
			cout << "Please enter the color: " << endl;
			cin >> color;
			points[i] = new LacksDMA(color, label, rating);
		}
		else if (selection == 3)
		{
			cout << "Please enter the label: " << endl;
			cin >> label;
			cout << "Please enter the rating: " << endl;
			cin >> rating;
			cout << "Please enter the sytle: " << endl;
			cin >> style;
			points[i] = new HasDMA(style, label, rating);
		}
		i++;
	}
	cout << "Reporting: " << endl;
	for (int i = 0; i < 3; i++)
	{
		points[i]->View();
	}


	system("pause");
	return 0;
}

//声明一个指针并不会为其分配内存,必须要通过new运算符或者将指针指向一个对象。

13.4

//class.h

#pragma once

#ifndef _CLASS_H_
#define _CLASS_H_

#include<iostream>
using namespace std;

class port
{
private:
	char* brand;
	char style[20];
	int bottles;
public:
	port(const char* br = "none", const char* st = "none", int b = 0);
	port(const port& p);
	virtual ~port()
	{
		delete[] brand;
	}
	port& operator=(const port& p);
	port& operator+=(int b);
	port& operator-=(int b);
	int BottleCount()const
	{
		return bottles;
	}
	virtual void Show()const;
	friend ostream& operator<<(ostream& os, const port& p);
};

class Vintageport :public port
{
private:
	char* nickname;
	int year;
public:
	Vintageport(const char* br = "none", const char*st = "none",int b = 0,  const char* nn = "none", int y = 0);
	Vintageport(const Vintageport& vp);
	~Vintageport()
	{
		delete[]nickname;
	}
	Vintageport& operator=(const Vintageport& vp);
	void Show()const;
	friend ostream& operator<<(ostream& os, const Vintageport& vp);
};




#endif

//fuc.cpp

#include<cstring>
#include"class.h"

#pragma warning(disable:4996)

//base
port::port(const char* br, const char* st, int b)
{
	brand = new char[strlen(br) + 1];
	strcpy(brand, br);
	strcpy(style, st);
	bottles = b;
}

port::port(const port& p)
{
	brand = new char[strlen(p.brand) + 1];
	strcpy(brand, p.brand);
	strcpy(style, p.style);
	bottles = p.bottles;
}

port& port::operator=(const port& p)
{
	delete[]brand; //赋值是对于已经初始化过的对象使用的,所以相当于复制构造函数是针对未初始化的对象,要多一步delete防止内存的损耗
	brand = new char[strlen(p.brand) + 1];
	strcpy(brand, p.brand);
	strcpy(style, p.style);
	bottles = p.bottles;
	return *this;
}

port& port::operator+=(int b)
{
	bottles += b;
	return *this;
}

port& port::operator-=(int b)
{
	if (bottles < 0)
	{
		cout << "There are no bottles left" << endl;
		return *this;
	}
	else
	{
		bottles -= b;
		return *this;
	}
}

void port::Show()const
{
	cout << "Brand: " << brand << endl;
	cout << "Kind: " << style << endl;
	cout << "Bottles: " << bottles << endl;
}

ostream& operator<<(ostream& os, const port& p)
{
	os << p.brand << " ," << p.style << " ," << p.bottles << endl;
	return os;
}

//derived
Vintageport::Vintageport(const char* br, const char* st,int b, const char* nn, int y):port(br,st,b)
{
	nickname = new char[strlen(nn) + 1];
	strcpy(nickname, nn);
	year = y;
}

Vintageport::Vintageport(const Vintageport& vp):port(vp)
{
	nickname = new char[strlen(vp.nickname) + 1];
	strcpy(nickname, vp.nickname);
	year = vp.year;
}

Vintageport& Vintageport::operator=(const Vintageport& vp)
{
	port::operator=(vp); //调用基类的重载赋值运算符
	delete[]nickname;
	nickname = new char[strlen(vp.nickname) + 1];
	strcpy(nickname, vp.nickname);
	year = vp.year;
	return *this;
}
void Vintageport::Show()const
{
	port::Show(); //基类部分
	cout << "Nickname: " << nickname << endl;
	cout << "Year: " << year << endl;
}

//友元函数无需声明是哪个类中的,因为友元函数不属于成员函数
ostream& operator<<(ostream& os, const Vintageport& vp)
{
	//通过强制类型转换来访问基类的友元函数:将派生类参数转换为基类参数来匹配基类的友元函数
	cout << (const port&)vp << ", " << vp.nickname << ", " << vp.year << endl;
	return os;
}

//main.cpp

#include"class.h"

int main()
{
	port p1("GodFishhh", "Fishing", 10);
	port p2("AFish", "Fish", 20);
	cout <<"p1: "<< p1 << endl;
	cout <<"p2: " << p2 << endl;
	p1.Show();
	p2.Show();
	p1 += 10;
	p2 -= 5;
	cout << "After refreshing: " << endl;
	p1.Show();
	p2.Show();
	Vintageport v1("GodFishhh", "Fishing", 10, "AFish", 20);
	cout << "V1: " << v1 << endl;
	v1.Show();

	system("pause");
	return 0;
}

//通过强制类型转换来访问基类的友元函数:将派生类参数转换为基类参数以匹配基类的友元函数。

//友元函数无需声明位于哪里类中,因为友元函数不属于类成员函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值