Bootstrap

C++ primer plus第十四章编程练习答案

1.Wine 类有一个string 类对象成员(参见第4章)和一个Pair 对象(参见本章)其中前者用于存储葡酒的名称而后者有2个valarray<in对象(参见本章)这两个 valaray<in对象分别保了葡酒的酿造年份和该年生产的瓶数。例如Pair 的第1个 valaray<int对象可能为19881992和1996年第2个alaay<int对象可能为24、48和144瓶。Wine 最好有1个nt 成员用于存储年数另外,一些 typedef 可能有助于简化编程工作:
typedef std::valarrayeints ArrayInt ;

typedef Pair<ArrayInt,ArrayInt> PairArray;
这样,PairArray表示的是类型 Pair<std:valarray<in>std:valaay<in> >使用包含来实现 Wine类并用个简单的程序对其进行测试。Wine 类应该有一个默认构造函数以及如下构造函数:
// initialize label to l,number of years to y.

// vintage years to yr[], bottles to bot[]

Wine(const char *l,int y, const int yr[], const int bot[l);

// initialize label to l, number of years to y.

// create array objects of length y
Winelconst char *l,int y);Wine 类应该有一个GetBottles()方法,它根据 Wine 对象能够存储儿种年份(y),提示用户输入年份和瓶数。方法Label()返回一个指向葡萄酒名称的引用。sm()方法返回 Pair 对象中第二个valaay<in对象中的瓶数总和测试程序应提示用户输入葡萄酒名称、元素个数以及每个元素存储的年份和瓶数等信息。程序将使用这些数据来构造一个 Wine对象,然后显示对象中保存的信息。
下面是一个简单的测试程序:

//pe14-1.cpp-- using Wine class with containment#include ciostream>#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 number of years: *;
int yrs;
cin>> yrs;
Wine holding(lab,yrs); // store label,years,give arrays yrs elementsholding.GetBottles();// solicit input for year, bottle countholding.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 bWine more("Gushing Grape Red",YRS,y.b);
more .Show():cout << "Total bottles for" <e more,Label() // use Label() method<< "; n cc more,sum() c< endl:// use sum() methodcout <<"Bye\n"
return 0;

下面是该程序的运行情况:
Enter name of wine: Gully Wash
Enter number of years: 4
Enter Gully Wash data for 4 year(s):
Enter year: 1988
Enter bottles for that year: 42
Enter year: 1994
Enter bottles for that year: 58
Enter year: 1998
Enter bottles for that year: 122
Enter year:2001
Enter bottles for that year: 144
Wine: Gully Wash
Year
1988
1994
1998
2001
Bottles
42
58
122
144
Wine: Gushing
Grape Red
Year
1993
1995
1998
Bottles
48
60
72
Total bottles for Gushing Grape Red: 180Bye

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

int main()
{
    using std::cin;
    using std::cout;
    using std::endl;

    cout << "Enter name of wine: ";
    char lab[50];
    cin.getline(lab, 50);
    cout << "Enter number of years: ";
    int yrs;
    cin >> yrs;

    Wine holding(lab, yrs);
    holding.GetBottles();
    holding.Show();

    const int YRS = 3;
    int y[YRS] = {1993, 1995, 1998};
    int b[YRS] = {48, 60, 72};

    Wine more("Gushing Grape Red", YRS, y, b);
    more.Show();
    cout << "Total bottles for " << more.Label();
    cout << ": " << more.sum() << endl;
    cout << "Bye\n";

    return 0;
}
#ifndef WINEC_H_
#define WINEC_H_
#include <string>
#include <valarray>
#include <iostream>
using namespace std;

template <typename T1, typename T2>
class Pair
{
private:
    T1 year;
    T2 bottles;

public:
    Pair() {}
    Pair(const T1 &yr, const T2 &bt) : year(yr), bottles(bt) {}
    void Set(const T1 &yr, const T2 &bt);
    int Sum() const;
    void Show(int y) const;
};

template <typename T1, typename T2>
void Pair<T1, T2>::Set(const T1 &yr, const T2 &bt)
{
    year = yr;
    bottles = bt;
}

template <typename T1, typename T2>
int Pair<T1, T2>::Sum() const
{
    return bottles.sum();
}

template <typename T1, typename T2>
void Pair<T1, T2>::Show(int y) const
{
    for (int i = 0; i < y; i++)
    {
        cout << "\t" << year[i] << "\t" << bottles[i] << endl;
    }
}

typedef valarray<int> ArrayInt;
typedef Pair<ArrayInt, ArrayInt> PairArray;

class Wine
{
private:
    string wine_name;
    PairArray year_and_bottle;
    int year;

public:
    Wine(const char *l, int y);
    Wine(const char *l, int y, const int yr[], const int bot[]);
    ~Wine();
    void GetBottles();
    string &Label();
    int sum() const;
    void Show() const;
};

#endif
#include "winec.h"

Wine::Wine(const char *l, int y)
{
    wine_name = l;
    year_and_bottle.Set(ArrayInt(y), ArrayInt(y));
    year = y;
}

Wine::Wine(const char *l, int y, const int yr[], const int bot[])
{
    wine_name = l;
    year_and_bottle.Set(ArrayInt(yr, y), ArrayInt(bot, y));
    year = y;
}

Wine::~Wine()
{
}

void Wine::GetBottles()
{
    ArrayInt yr(year);
    ArrayInt bt(year);

    cout << "Enter " << wine_name;
    cout << " data for " << year << " year(s):" << endl;
    for (int i = 0; i < year; i++)
    {
        cout << "Enter year: ";
        cin >> yr[i];
        cout << "Enter bottles for that year: ";
        cin >> bt[i];
    }
    year_and_bottle.Set(yr, bt);
}

string &Wine::Label()
{
    return wine_name;
}

int Wine::sum() const
{
    return year_and_bottle.Sum();
}

void Wine::Show() const
{
    cout << "Wine: " << wine_name << endl;
    cout << "\tYear\tBottles" << endl;
    year_and_bottle.Show(year);
}

2.采用私有继承而不是包含来完成编程练习 1。同样,一些 yedef 可能会有所帮助,另外,您可能还需要考电诸如下面这样的语句的含义:
PairArray::operator=(PairArray(ArrayInt [),ArrayInt()));cout cc(const string &)(*this);
您设计的类应该可以使用编程练习1中的测试程序进行测试。

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

int main()
{
    using std::cin;
    using std::cout;
    using std::endl;

    cout << "Enter name of wine: ";
    char lab[50];
    cin.getline(lab, 50);
    cout << "Enter number of years: ";
    int yrs;
    cin >> yrs;

    Wine holding(lab, yrs);
    holding.GetBottles();
    holding.Show();

    const int YRS = 3;
    int y[YRS] = {1993, 1995, 1998};
    int b[YRS] = {48, 60, 72};

    Wine more("Gushing Grape Red", YRS, y, b);
    more.Show();
    cout << "Total bottles for " << more.Label();
    cout << ": " << more.sum() << endl;
    cout << "Bye\n";

    return 0;
}
#ifndef WINEC_H_
#define WINEC_H_
#include <string>
#include <valarray>
#include <iostream>
using namespace std;

template <typename T1, typename T2>
class Pair
{
private:
    T1 year;
    T2 bottles;

public:
    Pair() {}
    Pair(const T1 &yr, const T2 &bt) : year(yr), bottles(bt) {}
    int Sum() const;
    void Show(int y) const;
};

template <typename T1, typename T2>
int Pair<T1, T2>::Sum() const
{
    return bottles.sum();
}

template <typename T1, typename T2>
void Pair<T1, T2>::Show(int y) const
{
    for (int i = 0; i < y; i++)
    {
        cout << '\t' << year[i] << '\t' << bottles[i] << endl;
    }
}

typedef valarray<int> ArrayInt;
typedef Pair<ArrayInt, ArrayInt> PairArray;

class Wine : private string, private PairArray
{
private:
    int year;

public:
    Wine(const char *l, int y);
    Wine(const char *l, int y, const int yr[], const int bot[]);
    ~Wine();
    void GetBottles();
    string &Label();
    int sum() const;
    void Show() const;
};

#endif
#include "winec.h"

Wine::Wine(const char *l, int y) : string(l)
{
    PairArray::operator=(PairArray(ArrayInt(y), ArrayInt(y))); //使用隐式赋值运算符调用私有对象构造函数进行初始化;
    year = y;
}

Wine::Wine(const char *l, int y, const int yr[], const int bot[]) : string(l)
{
    PairArray::operator=(PairArray(ArrayInt(yr, y), ArrayInt(bot, y))); //使用隐式赋值运算符调用私有对象构造函数进行初始化;
    year = y;
}

Wine::~Wine()
{
}

void Wine::GetBottles()
{
    ArrayInt yr(year);
    ArrayInt bt(year);

    cout << "Enter " << (const string &)*this;
    cout << " data for " << year << " year(s):" << endl;
    for (int i = 0; i < year; i++)
    {
        cout << "Enter year: ";
        cin >> yr[i];
        cout << "Enter bottles for that year: ";
        cin >> bt[i];
    }
    PairArray::operator=(PairArray(yr, bt));
}

string &Wine::Label()
{
    return (string &)*this; //使用强制类型转换访问私有对象;
}

int Wine::sum() const
{
    return PairArray::Sum();
}

void Wine::Show() const
{
    cout << "Wine: " << (const string &)(*this) << endl;
    cout << "\tYear\tBottles" << endl;
    PairArray::Show(year);
}

3.定义一个QucueTp 模板。然后在一个类似于程序清单14.12 的程序中创建一个指向 Worker 的指针队列(参见程序清单14.10中的定义),并使用该队列来测试它。

#include <iostream>
#include <cstring>
#include "worker.h"
#include "queuetp.h"
const int SIZE = 5;

int main()
{
    using std::cin;
    using std::cout;
    using std::endl;
    using std::strchr;

    int ct;
    Worker *temp;
    QueueTp<Worker *> lolas(SIZE);

    for (ct = 0; ct < SIZE; ct++)
    {
        char choice;
        cout << "Enter the menu order:" << endl;
        cout << "a: add a worker to queue." << endl;
        cout << "d: delete a worker from queue." << endl;
        cout << "q: quit." << endl;
        cin >> choice;
        while (NULL == strchr("adq", choice))
        {
            cout << "Please enter a, d or q: ";
            cin >> choice;
        }
        if ('q' == choice)
        {
            break;
        }
        switch (choice)
        {
        case 'a':
        {
            temp = new Worker;
            cin.get();
            if (lolas.isfull()) //若是队列已满则打印信息并释放new分配的内存;
            {
                cout << "Queue is full!" << endl;
                delete temp;
            }
            else
            {
                temp->Set();
                lolas.enqueue(temp);
            }
            break;
        }
        case 'd':
        {
            if (lolas.isempty())
            {
                cout << "Queue is empty!" << endl;
            }
            else
            {
                lolas.dequeue(temp);
            }
            break;
        }
        }
    }
    ct = lolas.queuecount();
    cout << "\nHere is " << ct << " worker(s) in queue:" << endl;
    for (int i = 0; i < ct; i++)
    {
        lolas.dequeue(temp);
        temp->Show();
    }
    cout << "Done.\n";

    return 0;
}
#ifndef QUEUETP_H_
#define QUEUETP_H_

template <typename Item>
class QueueTp
{
private:
    enum{ Q_SIZE = 10 };
    struct Node
    {
        Item item;
        struct Node *next;
    };
    Node *front;
    Node *rear;
    int items;
    const int qsize;
    QueueTp(const QueueTp &q) : qsize(0) {}
    QueueTp &operator=(const QueueTp &q) { return *this; }

public:
    QueueTp(int qs = Q_SIZE);
    ~QueueTp();
    bool isempty() const;
    bool isfull() const;
    int queuecount() const;
    bool enqueue(const Item &item);
    bool dequeue(Item &item);
};

template <typename Item>
QueueTp<Item>::QueueTp(int qs) : qsize(qs)
{
    front = rear = nullptr;
    items = 0;
}

template <typename Item>
QueueTp<Item>::~QueueTp()
{
    Node *temp;

    while (front != nullptr)
    {
        temp = front;
        front = front->next;
        delete temp;
    }
}

template <typename Item>
bool QueueTp<Item>::isempty() const
{
    return 0 == items;
}

template <typename Item>
bool QueueTp<Item>::isfull() const
{
    return qsize == items;
}

template <typename Item>
int QueueTp<Item>::queuecount() const
{
    return items;
}

template <typename Item>
bool QueueTp<Item>::enqueue(const Item &item)
{
    if (isfull())
    {
        return false;
    }
    Node *add = new Node;
    add->item = item;
    add->next = nullptr;
    ++items;
    if (nullptr == front)
    {
        front = add;
    }
    else
    {
        rear->next = add;
    }
    rear = add;
    return true;
}

template <typename Item>
bool QueueTp<Item>::dequeue(Item &item)
{
    if (isempty())
    {
        return false;
    }
    item = front->item;
    --items;
    Node *temp = front;
    front = front->next;
    delete temp;
    if (0 == items)
    {
        rear = nullptr;
    }
    return true;
}

#endif
#ifndef WORKER_H_
#define WORKER_H_
#include <string>

class Worker
{
private:
    std::string fullname;
    long id;

public:
    Worker() : fullname("no one"), id(0L) {}
    Worker(const std::string &s, long n) : fullname(s), id(n) {}
    ~Worker();
    void Set();
    void Show() const;
};

#endif

4.Pcrson 类保存人的名和姓。除构造函数外,它还有 Show( )方法,用于显示名和姓。Guslinger 类以Person类为虚基类派生而来,它包含一个Draw( )成员,该方法返回一个double值,表示枪手的拔枪时间。这个类还包含一个int 成员,表示枪手枪上的刻痕数。最后,这个类还包含一个 Show()两数,用于显示所有这些信息。
PokerPlayer 类以Person类为虚基类派生而来。它包含一个Draw( )成员该函数返回一个1~52的随机数,用于表示扑克牌的值(也可以定义一个 Card 类,其中包含花色和面值成员,然后让 Draw( )返回一个Card对象)。PokerPlayer类使用 Person 类的 show()数。BadDude( )类从Gunslingcr和 PokerPlayer类公有派生而来。它包含 Gdraw()成员(返回坏蛋拔枪的时间)和Cdraw()成员(返回下一张扑克牌),另外还有一个合适的 Show()函数。请定义这些类和方法以及其他必要的方法(如用于设置对象值的方法),并使用一个类似于程序清单14.12 的简单程序对它们进行测试。

#include <iostream>
#include <cstring>
#include "personmi.h"
const int SIZE = 5;

int main()
{
    using std::cin;
    using std::cout;
    using std::endl;
    using std::strchr;

    int i, ct;
    Person *people[SIZE];

    for (ct = 0; ct < SIZE; ct++)
    {
        char choice;
        cout << "Enter the person category:" << endl;
        cout << "g: gunslinger" << endl;
        cout << "p: pokerplayer" << endl;
        cout << "b: baddude" << endl;
        cout << "q: quit" << endl;
        cin >> choice;
        while (NULL == strchr("bgpq", choice))
        {
            cout << "Please enter b, g, p or q: ";
            cin >> choice;
        }
        if ('q' == choice)
        {
            break;
        }
        switch (choice)
        {
        case 'b':
        {
            people[ct] = new BadDude;
            break;
        }
        case 'g':
        {
            people[ct] = new Gunslinger;
            break;
        }
        case 'p':
        {
            people[ct] = new PokerPlayer;
            break;
        }
        }
        cin.get();
        people[ct]->Set();
    }
    cout << "\nHere is your message for some people:" << endl;
    for (i = 0; i < ct; i++)
    {
        cout << endl;
        people[i]->Show();
    }
    for (i = 0; i < ct; i++)
    {
        delete people[i];
    }
    cout << "Bye.\n";

    return 0;
}
#ifndef PERSONMI_H_
#define PERSONMI_H_
#include <string>
using std::string;

class Person
{
private:
    string firstname;
    string lastname;

protected:
    virtual void Data() const; //虚保护方法打印基类成员信息, 使得派生类可以间接访问;
    virtual void Get();        //虚保护方法获取基类成员信息, 使得派生类可以间接访问;

public:
    Person() : firstname("no"), lastname("one") {}
    Person(const string &fname, const string &lname) : firstname(fname), lastname(lname) {}
    virtual ~Person() = 0;
    virtual void Set() = 0;
    virtual void Show() const = 0;
};

class Gunslinger : virtual public Person
{
private:
    int nicks;

protected:
    void Data() const; //重新定义保护方法;
    void Get();

public:
    Gunslinger() : Person(), nicks(0) {}
    Gunslinger(const string &f, const string &l, int n) : Person(f, l), nicks(n) {}
    Gunslinger(const Person &p, int n) : Person(p), nicks(n) {}
    void Set();
    void Show() const;
    double Draw() const; //打印枪手的拔枪时间;
};

class PokerPlayer : virtual public Person
{
protected:
    void Data() const; //重新定义保护方法;

public:
    PokerPlayer() : Person("no", "one") {}
    PokerPlayer(const string &f, const string &l) : Person(f, l) {}
    PokerPlayer(const Person &p) : Person(p) {}
    void Set();
    void Show() const;
    int Draw() const; //表示扑克牌的值;
};

class BadDude : public Gunslinger, public PokerPlayer
{
protected:
    void Data() const; //重新定义保护方法;
    void Get();

public:
    BadDude() {}
    BadDude(const string &f, const string &l, int n) : Person(f, l), Gunslinger(f, l, n), PokerPlayer(f, l) {}
    BadDude(const Person &p, int n) : Person(p), Gunslinger(p, n), PokerPlayer(p) {}
    BadDude(const Gunslinger &g) : Person(g), Gunslinger(g), PokerPlayer(g) {}
    BadDude(const PokerPlayer &p, int n) : Person(p), Gunslinger(p, n), PokerPlayer(p) {}
    void Set();
    void Show() const;
    double Gdraw() const; //打印坏蛋拔枪的时间;
    int Cdraw() const;    //打印下一张扑克牌的值;
};

#endif
#include <iostream>
#include <cstdlib>
#include "personmi.h"
using namespace std;

Person::~Person()
{
}

void Person::Data() const
{
    cout << "First name: " << firstname << endl;
    cout << "Last name: " << lastname << endl;
}

void Person::Get()
{
    cout << "Please enter your first name: ";
    getline(cin, firstname);
    cout << "Please enter your last name: ";
    getline(cin, lastname);
}

void Gunslinger::Data() const
{
    cout << "Gunslinger nicks: " << nicks << endl;
}

void Gunslinger::Get()
{
    cout << "Please enter the nicks for gunslinger: ";
    cin >> nicks;
    while (cin.get() != '\n')
        continue;
}

void Gunslinger::Set()
{
    cout << "Enter Gunslinger name" << endl;
    Person::Get();
    Get();
}

void Gunslinger::Show() const
{
    cout << "Category: Gunslinger" << endl;
    Person::Data();
    Data();
}

double Gunslinger::Draw() const
{
    return double(rand() % 5 + 1); //枪手的拔枪时间设置为1到5之间的值;
}

void PokerPlayer::Data() const
{
    cout << "The cards: " << Draw() << endl;
}

void PokerPlayer::Set()
{
    cout << "Enter PokerPlayer name" << endl;
    Person::Get();
}

void PokerPlayer::Show() const
{
    cout << "Category: PokerPlayer" << endl;
    Person::Data();
    Data();
}

int PokerPlayer::Draw() const //扑克牌的值;
{
    return rand() % 52 + 1;
}

void BadDude::Data() const
{
    Gunslinger::Data();
    PokerPlayer::Data();
    cout << "The time for a bad guy to draw his gun is " << Gdraw() << endl;
    cout << "The next card is " << Cdraw() << endl;
}

void BadDude::Get()
{
    Gunslinger::Get();
}

void BadDude::Set()
{
    cout << "Enter BadDude name" << endl;
    Person::Get();
    Get();
}

void BadDude::Show() const
{
    cout << "Category: BadDude" << endl;
    Person::Data();
    Data();
}

double BadDude::Gdraw() const
{
    return Gunslinger::Draw();
}

int BadDude::Cdraw() const
{
    return PokerPlayer::Draw();
}

5.下面是一些雷声明:

// emp.h -- header file for abstr_emp class and children
#include ciostream>

#include catringx
class abstr emp
private :
// abstremp's first name

std ::string fname ;

std::string lname;// abstr_emp's last name
std;:atring job;
public:
abstr_empl);
abatr_empiconst std::string k fn, const std::string 6 ln,const std::string & j);virtual void ShowAll] const;// labels and shows all datavirtual void SetAl1(),/ prompts user for valuesfriend std;iostream k
operatorcc(std;:ostream k o8, const abstr emp & e);// just displays first and last name// virtual base classvirtual -abstrempl)m0;
class employee : public abstr emp
public:
employee(l;
employee(const std;istring 5 fn,const std;:string 点 ln,const std;string & j;virtual void ShowAll() const;virtual void SetAl1();
tr
class manager: virtual public abstr emp
private:int inchargeof;// number of abatr emps managedprotected:
int InCharge0f () const  return inchargeof; // outputint & InChargeOfl! return inehargeof ;// inputpublie:
manager():manager(const std::string & fn, const std::string 5 In.const atd::string  j, int ico  0;manager(const abetr_emp & e,int ico] ?
manager(const manager & m) :
virtual void ShowAll() const :
virtual vold SetAl1 ();
clagm fink; virtual public abatr emp
private:
std::string reportsto;protected;..2ri
..:to whomfink reports
.const atd=;string ReportsTol) const -[ return-reportsto;std::string & ReportsTo() return reportsto;public:·.-
fink(》;
fink(const std::string &fn, const std::string 6 In,conststd!:string  j,const std::string arpolifinkIconstabstr-emp se,const  std::string .rpol:fink(consttink & e)virtuaFvoid-ShowAll[-const;virtual void SetAlIU
class highfink:public manager,public fink // managementfink-
public-
highfink(Congtstd:::string' fn,const std::string&.In,;const_std?:string &const'std;rstring 5rpo.intvicor+-TI
highfink(const abstr_emp& e,.const;std::string & rpo;int ico);
highfink(const,fink &f,int.ico).
highfinklconst manager &m,const std::string& rpol;
highfinklconst highfink & h .
virtual void ShowAl1[),const;virtua] voidSetAll(F;:-

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

/pe14-5:cPP//useemp1-cPP
--_usingthe'abstr emp,classes
--
#include <iostream>using,namespace std;#inElude "emp,h"ac
int main(voidl
employeeem("Trip","Harr""Thumper")-cout << em <s endl;em,ShowA11(l;managerma["Amorphia","Spindragon'"Nuancer!.-5);cout << ma <<endl;
ma,showAIIT]:
fink'fi("Matt","Oggs","Oiler”,"Juno Barr");cout cc fi *<endl;

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

为什么没有定义赋值运算符?为什么要将 showA11()和 SetA11()定义为的?为什么要将abstr_emp 定义为虚基类?为什么highfink 类没有数据部分?为什么只需要一个 operator<<()版本?如果使用下面的代码替换程序的结尾部分,将会发生什么情况?

abstr_emp tri[] - (em,fi,hf,hf2);

for  (inti=0;ic4;i++)
tri[i].ShowAll();

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

int main()
{
    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");
    hf.ShowAll();
    cout << "Press a key for next phase:\n";
    cin.get();
    highfink hf2;
    hf2.SetAll();

    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;
}
#ifndef EMP_H_
#define EMP_H_
#include <iostream>
#include <string>

class abstr_emp
{
private:
    std::string fname;
    std::string lname;
    std::string job;

public:
    abstr_emp();
    abstr_emp(const std::string &fn, const std::string &ln, const std::string &j);
    virtual void ShowAll() const;
    virtual void SetAll();
    friend std::ostream &operator<<(std::ostream &os, const abstr_emp &e);
    virtual ~abstr_emp() = 0;
};

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 SetAll();
};

class manager : virtual public abstr_emp
{
private:
    int inchargeof;

protected:
    int InChargeOf() const { return inchargeof; } //令派生类能够访问基类成员;
    int &InChargeOf() { return inchargeof; }      //令派生类能够访问基类成员并进行修改;

public:
    manager();
    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();
};

class fink : virtual public abstr_emp
{
private:
    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 abstr_emp &e, const std::string &rpo);
    fink(const fink &e);
    virtual void ShowAll() const;
    virtual void SetAll();
};

class highfink : public manager, public fink
{
public:
    highfink();
    highfink(const std::string &fn, const std::string &ln, const 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 SetAll();
};

#endif
#include <iostream>
#include <string>
#include "emp.h"
using std::cin;
using std::cout;
using std::endl;
using std::string;

abstr_emp::abstr_emp() : fname("no"), lname("one"), job("none")
{
}

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

void abstr_emp::ShowAll() const
{
    cout << "First name: " << fname << endl;
    cout << "Last name: " << lname << endl;
    cout << "Job: " << job << endl;
}

void abstr_emp::SetAll()
{
    cout << "Please enter your firstname: ";
    getline(cin, fname);
    cout << "Please enter your lastname: ";
    getline(cin, lname);
    cout << "Please enter your job: ";
    getline(cin, job);
}

std::ostream &operator<<(std::ostream &os, const abstr_emp &e)
{
    os << "First name: " << e.fname << endl;
    os << "Last name: " << e.lname << endl;
    os << "Job: " << e.job;
    return os;
}

abstr_emp::~abstr_emp()
{
}

employee::employee() : abstr_emp()
{
}

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

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

void employee::SetAll()
{
    abstr_emp::SetAll();
}

manager::manager() : abstr_emp(), inchargeof(0)
{
}

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

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

manager::manager(const manager &m) : abstr_emp(m), inchargeof(m.inchargeof)
{
}

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

void manager::SetAll()
{
    abstr_emp::SetAll();
    cout << "Please enter a number for inchargerof: ";
    cin >> inchargeof;
    while (cin.get() != '\n')
        continue;
}

fink::fink() : abstr_emp(), reportsto("none")
{
}

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

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

fink::fink(const fink &e) : abstr_emp(e), reportsto(e.reportsto)
{
}

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

void fink::SetAll()
{
    abstr_emp::SetAll();
    cout << "Please enter a string for reportsto: ";
    getline(cin, reportsto);
}

highfink::highfink() : abstr_emp(), manager(), fink()
{
}

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

highfink::highfink(const abstr_emp &e, const string &rpo, int ico) : abstr_emp(e), manager(e, ico), fink(e, rpo)
{
}

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

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

highfink::highfink(const highfink &h) : abstr_emp(h), manager(h), fink(h)
{
}

void highfink::ShowAll() const
{
    abstr_emp::ShowAll();
    cout << "In charge of: " << manager::InChargeOf() << endl;
    cout << "Reports to: " << fink::ReportsTo() << endl;
}

void highfink::SetAll()
{
    abstr_emp::SetAll();
    cout << "Please enter a number for inchargerof: ";
    cin >> InChargeOf();
    while (cin.get() != '\n')
        continue;
    cout << "Please enter a string for reportsto: ";
    getline(cin, ReportsTo());
}

(1):因为没有使用new进行动态内存分配因此使用的是隐式赋值运算符。
(2):在派生类中进行了再次定义,所以声明为虚函数。
(3):使得从多个类(基类相同)派生出的对象只继承1个基类对象。
(4):没有新增的数据成员,继承过来的数据成员需用基类方法间接访问。
(5):因为只访问对象中的3个数据部分,其余部分未进行访问。
(6):编译器将会报错,抽象基类不能进行实例化,但可以使用抽象基类的指针来访问派生出来的多个不同类。

;