C++Primer Plus 第十四章代码重用:编程习题总览
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:编程习题总览
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
14.7 编程练习
1.
Wine 类有一个 sting类对象成员(参见第4章)和一个Pair 对象(参见本章);其中前者用于存储葡萄酒的名称,而后者有2个valamray<inp对象(参见本章),这两个valanay对象分别保存了葡萄酒的酿造年份和该年生产的瓶数。例如,Pair的第1个valarray对象可能为1988、1992和1996年,第2个valarray对象可能为 24、48和144瓶。Wine 最好有1个imnt 成员用于存储年数。另外,一些typedef可能有助于简化编程工作:
typedef std::valarray<int> ArrayInt;
typedef Pair<ArrayInt,ArrayInt> PairArray;
这样,PairAmray 表示的是类型 Pair<std::valarray,std:valarray>。使用包含来实现 Wine 类,并用一个简单的程序对其进行测试。Wine 类应该有一个默认构造函数以及如下构造函数:
//initialize label to l,number of years to y,
//vintage years to yrl],bottles to bot[]
wine(const char*l,int y,const int yr[],const int bot[]);
//initialize label to l,number of years to y.
//create array objects of length y
Wine(const char*l int y);
Wimne 类应该有一个 GetBotles()方法,它根据 Wine 对象能够存储儿种年份(y),提示用户输入年份和瓶数。方法 Label()返回一个指向葡萄酒名称的引用。sum()方法返回 Pair 对象中第二个 valamay对象中的瓶数总和。测试程序应提示用户输入葡萄酒名称、元素个数以及每个元素存储的年份和瓶数等信息。程序将使用这些数据来构造一个 Wine 对象,然后显示对象中保存的信息。
下面是一个简单的测试程序:
// pe14-1.cpp--using Wine class with containment
#include <iostream>
#include "winec.h"
int main (void )
{
using std::cin;
using std::cout;
using std::endl;
cout <<"Enter name of wine:";
char lab[50];
cin.getline(lab,50);
cout <<"Enter numberofyears:";
int yrs;
cin >>yrs;
Wine holding(lab,yrs);//store label,years,give arrays yrs elements
holding.GetBottles();//solicit input for year,bottle count
holding.show();//display object contents
const int YRs =3;
int y[YRs]={1993,1995,1998};
int b[YRs]={48,60,72};
//create new object,initialize using data in arrays y and b
Wine more("Gushing Grape Red",YRS,y,b);
more.Show();
cout << "Total bottles for "<< more.Label()//use Label()method
<<":"<< more.sum()<< endl;//use sum()method
cout << "Bye\n";return 0;
}
下面是该程序的运行情况:
2.
采用私有继承而不是包含来完成编程练习1。同样,一些typedef可能会有所帮助,另外,您可能还需要考虑诸如下面这样的语句的含义:
PairArray::operator=(PairArray(ArrayInt(),ArrayInt()));
cout <<(const string &)(*this);
您设计的类应该可以使用编程练习1中的测试程序进行测试。
3.
定义一个 QueueTp 模板。然后在一个类似于程序清单 14.12 的程序中创建一个指向 Worker 的指针队列(参见程序清单14.10中的定义),并使用该队列来测试它。
4.
Person 类保存人的名和姓。除构造函数外,它还有 Show()方法,用于显示名和姓。Gunslinger 类以 Person 类为虚基类派生而来,它包含一个 Draw()成员,该方法返回一个 double 值,表示枪手的拔枪时间。这个类还包含一个int成员,表示枪手枪上的刻痕数。最后,这个类还包含一个 Show()函数,用于显示所有这些信息。
PokerPlayer 类以 Person 类为虚基类派生而来。它包含一个 Draw()成员,该函数返回一个1~52 的随机数,用于表示扑克牌的值(也可以定义一个Card 类,其中包含花色和面值成员,然后让 Draw()返回一个Card 对象)。PokerPlayer 类使用 Person 类的show()数。BadDude( )类从Gunslinger 和 PokerPlayer 类公有派生而来。它包含 Gdraw()成员(返回坏蛋拔枪的时间)和Cdraw()成员(返回下一张扑克牌),另外
还有一个合适的 Show()函数。请定义这些类和方法以及其他必要的方法(如用于设置对象值的方法),并使用一个类似于程序清单 14.12的简单程序对它们进行测试。
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();