C++Primer Plus 第十四章代码重用:编程练习,第5题

C++Primer Plus 第十四章代码重用:编程练习,第5题

C++Primer Plus 第十四章代码重用:编程练习,第5题



前言

5.

下面是一些类声明:


//emp.h--header file for abstr emp class and children

#include <iostream>
#include <string>

class abstr_emp
private :
std::string fname;// abstr emp's first name//abstr emp's last name
std::string lname;
std::string job;
public:
abstr_emp();
abstr_emp(const std::string &fn,const std::string & lnconst std::string&j);
virtual void showAll()const;// labels and shows all data
virtual void SetA1l();// prompts user for values
friend std::ostream &operator<<(std::ostream &os,const abstremp&e);//just displays first and last name
virtual ~abstr_emp()=0;
//virtual base class
class employee:public abstr_emp
{
public :
employee();
employee(const std::string &fn,const std::string&ln,const std::string&j);
virtual void ShowAll()const;
virtual void SetA1l();
}

class manager:virtual public abstr_emp
{
private :
int inchargeof;//number of abstr emps manaqed
protected:
int InCharge0f()const(return inchargeof;)// output
int & InChargeof()return {inchargeof};// input
public :
manager();
manager(const std::string &fn,const std::string & ln,const std::string&j,int ico=0);
manager(constabstremp&e,intico);
manager(const manager&m);
virtual void showAll()const;
virtual void SetA1l();
}

class fink:virtual public abstr_emp
{
private:
//to whom fink reports
std::string reportsto;
protected:
const std::string ReportsTo()const {return reportsto};
std::string &ReportsTo() {return reportsto};
public :
fink();
fink(const std::string & fn,const std::string & ln,const std::string&j,const std::string &rpo);
fink(const abstremp &e,const std::string &rpo);
fink(const fink & e);
virtual void ShowAll()const;
virtual void SetAl1();
}
class highfink: public manager,public fink // management finkpublic:
{
highfink();
highfink(const std::string &fn,const std::string & lnconst std::string&j,const std::string&rpo,int ico);
highfink(const abstr emp &e,const std::string & rpo,int ico);
highfink(const fink & f,int ico);
highfink(const manager &m,const std::string & rpo);
highfink(const highfink & h);
virtual void ShowAll()const;
virtual void setAl1();
}

注意,该类层次结构使用了带虚基类的 M,所以要牢记这种情况下用于构造函数初始化列表的特殊规则。还需要注意的是,有些方法被声明为保护的。这可以简化一些highfnk方法的代码(例如,如果highfink::ShowAll( )只是调用 fink::ShowAll()和manager::ShwAll( ),则它将调用 abstr_emp::ShowAl( )两次)。请提供类方法的实现,并在一个程序中对这些类进行测试。下面是一个小型测试程序:

// pe14-5.cPp
// useemp1.cpp)-using the abstremp classes

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

int main(void)
{
employee em("Trip","Harris","Thumper" );
cout <<em< endl;
em.ShowAll();
manager ma("Amorphia","Spindragon""Nuancer"5);
Cout <<ma <endl;
ma .ShowAl1();
fink fi("Matt","Oggs","Oiler","Juno Barr");
cout << fi << endl;
fi.showA11();


highfink hf(ma,"Curly Kew");//recruitment?
hf.showA11();
cout <<"Press a key for next phase:\n";
cin.get();
highfink hf2;
hf2.setA11();
cout <<"Using an abstr emp *pointer:\n";
abstr emp *tri[4]={&em, &fi,&hf, &hf2};
for(inti=0;i<4;i++)
	tri[i]->showA11();
return 0;
}

  • 为什么没有定义赋值运算符?
  • 为什么要将ShowA11()和setA11()定义为虚的?
  • 为什么要将 abstr_emp 定义为虚基类?
  • 为什么 highfink类没有数据部分?
  • 为什么只需要一个operator<<()版本?
  • 如果使用下面的代码替换程序的结尾部分,将会发生什么情况?
abstr emp tri[4]={em,fi,hf,hf2);
for(inti=0;i<4;i++)
tri[i].ShowA11();


提示:以下是本篇文章正文内容,下面案例可供参考

一、方法

#include <iostream>
#include <limits>
#include <string>

using namespace std;

// ========================================
class abstr_emp
{
	private:
		std::string fname;	// abstr_emp's first name
		std::string lname;	// abstr_emp's last name
		std::string job;
		
	public:
		//abstr_emp();
		explicit abstr_emp(const std::string & fn = "", const std::string & ln = "", const std::string & j = "");
		virtual void ShowAll() const;	// labels and shows all data
		virtual void SetAll();		// prompts user for values
		friend std::ostream & operator<<(std::ostream & os, const abstr_emp & e);	// just displays first and last name
		virtual ~abstr_emp() = 0;	// virtual base class
};

abstr_emp::abstr_emp (const std::string & fn, const std::string & ln, const std::string & j)
	: fname(fn), lname(ln), job(j)
{
	;
}

abstr_emp::~abstr_emp ()
{
	;
}

void
abstr_emp::ShowAll () const
{
	cout	<< "name: " << fname << ' ' << lname << '\n'
			<< "job: " << job << endl;
}

void
abstr_emp::SetAll ()
{
	cout << "enter first name: ";
	cin >> fname;
	cin.clear();	// 清空输入缓冲区错误标志位
	cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');	// 清空输入缓冲区内容

	cout << "enter second name: ";
	cin >> lname;
	cin.clear();	// 清空输入缓冲区错误标志位
	cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');	// 清空输入缓冲区内容

	cout << "enter job: ";
	cin >> job;
	cin.clear();	// 清空输入缓冲区错误标志位
	cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');	// 清空输入缓冲区内容
}
	
std::ostream &
operator<< (std::ostream & os, const abstr_emp & e)
{
	e.ShowAll();
	return (os);
}


// ========================================
class employee : public abstr_emp
{
	public:
		//employee();
		explicit employee(const std::string & fn = "", const std::string & ln = "", const std::string & j = "");
		virtual void ShowAll() const;
		virtual void SetAll();
};

employee::employee (const std::string & fn, const std::string & ln, const std::string & j)
	: abstr_emp(fn, ln, j)
{
	;
}

void
employee::ShowAll () const
{
	abstr_emp::ShowAll();
}

void
employee::SetAll ()
{
	abstr_emp::SetAll();
}
	
// ========================================
class manager: virtual public abstr_emp
{
	private:
		int inchargeof;	// number of abstr_emps managed

	protected:
		int InChargeOf() const { return inchargeof; } // output
		int & InChargeOf(){ return inchargeof; }	// input

	public:
		//manager();
		explicit manager(const std::string & fn = "", const std::string & ln = "", const std::string & j = "", int ico = 0);
		manager(const abstr_emp & e, int ico);
		//manager(const manager & m);
		virtual void ShowAll() const;
		virtual void SetAll();
};

manager::manager (const std::string & fn, const std::string & ln, const std::string & j, int ico)
	: abstr_emp(fn, ln, j), inchargeof(ico)
{
	;
}

manager::manager (const abstr_emp & e, int ico)
	: abstr_emp(e), inchargeof(ico)
{
	;
}

void
manager::ShowAll () const
{
	abstr_emp::ShowAll();
	cout << "incharge of " << inchargeof << " employees" << endl;
}

void
manager::SetAll ()
{
	abstr_emp::SetAll();

	cout << "enter the number of managed: ";
	cin >> inchargeof;
	cin.clear();	// 清空输入缓冲区错误标志位
	cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');	// 清空输入缓冲区内容
}

// ========================================
class fink: virtual public abstr_emp
{
	private:
		std::string reportsto;	// to whom fink reports
	protected:
		const std::string ReportsTo() const { return reportsto; }
		std::string & ReportsTo(){ return reportsto; }
	public:
		//fink();
		fink(const std::string & fn = "", const std::string & ln = "", const std::string & j = "", const std::string & rpo = "");
		fink(const abstr_emp & e, const std::string & rpo);
		//fink(const fink & e);
		virtual void ShowAll() const;
		virtual void SetAll();
};

fink::fink (const std::string & fn, const std::string & ln, const std::string & j, const std::string & rpo)
	: abstr_emp(fn, ln, j), reportsto(rpo)
{
	;
}

fink::fink (const abstr_emp & e, const std::string & rpo)
	: abstr_emp(e), reportsto(rpo)
{
	;
}

void
fink::ShowAll () const
{
	abstr_emp::ShowAll();
	cout << "report to " << reportsto << endl;
}

void
fink::SetAll ()
{
	abstr_emp::SetAll();

	cout << "enter to whom fink reports: ";
	cin >> reportsto;
	cin.clear();	// 清空输入缓冲区错误标志位
	cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');	// 清空输入缓冲区内容
}

// ========================================
class highfink: public manager, public fink // management fink
{
	public:
		//highfink();
		explicit highfink(const std::string & fn = "", const std::string & ln = "", const std::string & j = "", const std::string & rpo = "", int ico = 0);
		//highfink(const abstr_emp & e, const std::string & rpo, int ico);
		highfink(const fink & f, int ico);
		highfink(const manager & m, const std::string & rpo);
		//highfink(const highfink & h);
		virtual void ShowAll() const;
		virtual void SetAll();
};

highfink::highfink (const std::string & fn, const std::string & ln, const std::string & j, const std::string & rpo, int ico)
	: abstr_emp(fn, ln, j), manager(fn, ln, j, ico), fink(fn, ln, j, rpo)
{
	;
}

highfink::highfink(const fink & f, int ico)
	: abstr_emp(f), manager(f, ico), fink(f)
{
	;
}

highfink::highfink (const manager & m, const std::string & rpo)
	: abstr_emp(m), manager(m), fink(m, rpo)
{
	;
}

void
highfink::ShowAll() const
{
	manager::ShowAll();
	cout << "report to " << ReportsTo() << endl;
}

void
highfink::SetAll()
{
	manager::SetAll();

	cout << "enter to whom fink reports: ";
	cin >> ReportsTo();
	cin.clear();	// 清空输入缓冲区错误标志位
	cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');	// 清空输入缓冲区内容
}

// ========================================
int main(void)
{
	employee em("Trip", "Harris", "Thumper");
	cout << em << endl;
	//em.ShowAll();

	manager ma("Amorphia", "Spindragon", "Nuancer", 5);
	cout << ma << endl;
	//ma.ShowAll();
	
	fink fi("Matt", "Oggs", "Oiler", "Juno Barr");
	cout << fi << endl;
	//fi.ShowAll();

	highfink hf(ma, "Curly Kew"); // recruitment?
	cout << hf << endl;
	//hf.ShowAll();
	cout << endl;
	
	cout << "Press a key for next phase:\n";
	cin.get();
	highfink hf2;
	hf2.SetAll();
	cout << endl;

	cout << "Using an abstr_emp * pointer:\n";
	abstr_emp * tri[4] = {&em, &fi, &hf, &hf2};
	for (int i = 0; i < 4; i++)
		tri[i]->ShowAll();
	
	return 0;
}

二、解答

Why is no assignment operator defined?
——abstr_emp、employee、manager、fink、highfink 等五个类内部并未涉及动态内存分配,并非深拷贝,因此,无须定义赋值运算符、拷贝构造函数、析构函数。

Why are ShowAll() and SetAll() virtual?
为什么要将 ShowAll() 和 SetAll() 定义为虚的?
——各级派生类均有各自新增的数据成员,显示、设置新增数据成员必须由派生类自行负责,无法直接复用基类的 ShowAll() 和 SetAll() 成员函数,在这两类操作上,派生类需要体现出类的多态特性。

Why is abstr_emp a virtual base class?
——若 abstr_emp 按一般方式派生出 manager、fink,而 manager、fink 派生出 highfink,highfink 将包含两份 abstr_emp 的数据成员,必须将 abstr_emp 通过 virtual 方式派生出 manager、fink,才能正常地只包含一份 abstr_emp 的数据成员。

Why does the highfink class have no data section?
——highfink 通过 manager、fink 多重继承而来,无须新增数据成员。

Why is only one version of operator<<() needed?
——friend std::ostream & operator<<(std::ostream & os, const abstr_emp & e) 的形参是基类引用,各派生类实现了各自的 virtual ShowAll() 函数,因此,operator<<() 在内部通过多态特性调用基类和派生类各自的 ShowAll() 实现输出。但是,书上的原型声明 virtual void ShowAll() const 有误,应改为 virtual std::ostream& ShowAll(std::ostream& os) const;

What would happen if the end of the program were replaced with this code?
abstr_emp tri[4] = {em, fi, hf, hf2};
for (int i = 0; i < 4; i++)
tri[i].ShowAll();
——语法错误,由于 abstr_emp 中含有纯虚成员函数,所以 abstr_emp 为抽象类,抽象类无法创建对象。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值