C++Primer Plus 第十四章代碼重用:編程練習,第5題
C++Primer Plus 第十四章代碼重用:編程練習,第5題
文章目錄
- C++Primer Plus 第十四章代碼重用:編程練習,第5題
- 前言
- 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 namestd::string lname; // abstr_emp's last namestd::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 datavirtual void SetAll(); // prompts user for valuesfriend std::ostream & operator<<(std::ostream & os, const abstr_emp & e); // just displays first and last namevirtual ~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 managedprotected:int InChargeOf() const { return inchargeof; } // outputint & InChargeOf(){ return inchargeof; } // inputpublic://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 reportsprotected: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 為抽象類,抽象類無法創建對象。