C++ Primier Plus(第六版) 第十四章 C++中的代码重用 编程练习答案

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

typedef std::valarray\<int> ArrayInt;
typedef Pair<ArrayInt,ArrayInt> PairArray;

这样, PairArray表示的是类型Pair<std::valarray<int>,std::valarray<int>>。使用包含来实现Wine类,并用一个简单的程序对其进行测试。Wine类应该有一个默认构造函数以及如下构造函数:

// intialize label to l, number of years to y
// vintage year to yr[], bottles to bot[]
Wine(const char * l, int y, const int yr[], const int bot[]);
// intialize label to l, number of years to y
// create array objects of length y
Wine(const char * l, int y);

Wine类应该有意v额GetBottles()方法,它根据Wine对象能够存储几种年份(y),提醒用户输入年份和瓶数。方法Label放回一个指向葡萄酒名称的引用。sum()方法返回Pair对象中第二个valarray<int>对象中的瓶数总和。
测试程序应提示用户输入葡萄酒名称、元素个数以及每个元素存储的年份和瓶数等信息。程序将使用这些数据构造一个Wine对象,然后显式对象中保存的信息。
下面是一个简单的测试程序:

// pe14-1.cpp -- using Wine class with containment
#include <iostream>
#include "winec.h"

int main(void)
{
	using std::cout;
	using std::cin;
	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 array 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, intialize 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;
}

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

本题不算难,但需要对valarray对象的方法比较熟悉,类Pair的定义与本章的定义一样,在实现构造函数时,笔者忘记给years赋值了,刚开始导致程序错误,后面初始化列表赋值后正确。本题使用的valarray方法有resize(); = {yr,size_t}; operator;,样例代码如下(测试代码为题目所给代码):

// wine.h -- definition of Wine class
#ifndef WINEC_H_
#define WINEC_H_
#include <string>
#include <valarray>

// template class Pair
template<typename T1, typename T2>
class Pair
{
private:
    T1 t1;
    T2 t2;
public:
    T1 & first() { return t1; }
    T2 & second() { return t2; }
    T1 first() const { return t1; }
    T2 second() const { return t2; }
    Pair(const T1 & t1val, const T2 & t2val) : t1(t1val), t2(t2val) {}
    Pair() {};
};

typedef std::valarray<int> ArrayInt;
typedef Pair<ArrayInt, ArrayInt> PairArrayInt;

class Wine
{
private:
    std::string name;
    PairArrayInt pai;
    int years;
public:
    Wine(const char * l = "no one", int y = 0);
    Wine(const char *l, int y, const int yr[], const int bot[]);
    void GetBottles();
    const std::string & Label() const { return name; }
    int sum() const;
    void Show() const;
};

#endif
// wine.cpp -- methods for Wine class
#include <iostream>
#include "winec.h"

// constructor
Wine::Wine(const char * l, int y) : name(l), years(y)
{
    pai.first().resize(years);
    pai.second().resize(years);
}

Wine::Wine(const char *l, int y, const int yr[], const int bot[])
         : name(l), years(y)
{
    pai.first() = {yr, (long long unsigned int)years};
    pai.second() = {bot, (long long unsigned int)years};
}

// input the bottles
void Wine::GetBottles()
{
    std::cout << "Enter " << Label() << " data for " 
              << years << " year(s): " << std::endl;
    for (int i = 0; i < years; i++)
    {
        std::cout << "Enter year: ";
        std::cin >> pai.first().operator[](i);
        std::cout << "Enter bottles for that year: ";
        std::cin >> pai.second().operator[](i);
    }
    // get all '\n'
    while (std::cin.get() != '\n')
        continue;
}

int Wine::sum() const
{
    return pai.second().sum();
}

void Wine::Show() const
{
    std::cout << "Wine: " << Label() << std::endl;
    std::cout << "\t\tYear\tBottles" << std::endl; 
    for (int i = 0; i < years; i++)
        std::cout << "\t\t" << pai.first()[i] 
                  << "\t" << pai.second()[i] << std::endl;
}

// ps: Wine::years forget to intialize

运行结果如下:
image

2.采用私有继承而不是包含来完成编程练习1。同样,一些typedef可能会有所帮助,另外,您可能还需要考虑诸如下面这样的语句的含义:

PairArray::operator = (PairArray(Arrayint(),ArrayInt()));
cout << (const string &) (*this);
您设计的类应该可以使用编程练习1中的测试程序进行测试。
本题将包含的关系转换成私有继承,头文件部分修改的程序不多,类方法实现部分主要修改的是构造函数,两个构造函数采用列表初始化的方法。代码如下:

// wine.h -- definition of Wine class
#ifndef WINEC_H_
#define WINEC_H_
#include <string>
#include <valarray>

// template class Pair
template<typename T1, typename T2>
class Pair
{
private:
    T1 t1;
    T2 t2;
public:
    T1 & first() { return t1; }
    T2 & second() { return t2; }
    T1 first() const { return t1; }
    T2 second() const { return t2; }
    Pair(const T1 & t1val, const T2 & t2val) : t1(t1val), t2(t2val) {}
    Pair() {};
};

typedef std::valarray<int> ArrayInt;
typedef Pair<ArrayInt, ArrayInt> PairArrayInt;

class Wine : private std::string, private PairArrayInt
{
private:
    int years;
public:
    Wine(const char * l = "no one", int y = 0);
    Wine(const char *l, int y, const int yr[], const int bot[]);
    void GetBottles();
    const std::string & Label() const { return (const std::string &) *this; }
    int sum() const;
    void Show() const;
};

#endif
// wine.cpp -- methods for Wine class
#include <iostream>
#include "winei.h"

// constructor
Wine::Wine(const char * l, int y) : std::string(l), years(y),
Pair(ArrayInt(y),ArrayInt(y)) { }

Wine::Wine(const char *l, int y, const int yr[], const int bot[])
         : std::string(l), years(y), 
         Pair(ArrayInt{yr,(long long unsigned int)y}, ArrayInt{bot, (long long unsigned int)y}) { }

// input the bottles
void Wine::GetBottles()
{
    std::cout << "Enter " << Label() << " data for " 
              << years << " year(s): " << std::endl;
    for (int i = 0; i < years; i++)
    {
        std::cout << "Enter year: ";
        std::cin >> Pair::first().operator[](i);
        std::cout << "Enter bottles for that year: ";
        std::cin >> Pair::second().operator[](i);
    }
    // get all '\n'
    while (std::cin.get() != '\n')
        continue;
}

int Wine::sum() const
{
    return Pair::second().sum();
}

void Wine::Show() const
{
    std::cout << "Wine: " << Label() << std::endl;
    std::cout << "\t\tYear\tBottles" << std::endl; 
    for (int i = 0; i < years; i++)
        std::cout << "\t\t" << Pair::first()[i] 
                  << "\t" << Pair::second()[i] << std::endl;
}
// pe14-2.cpp -- using Wine class with inhetitance
#include <iostream>
#include "winei.h"

int main(void)
{
	using std::cout;
	using std::cin;
	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 array 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, intialize 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;
}

运行结果如下:
image

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

本题考查的是定义队列模板,同时用该队列管理指针。程序编写时没有遇到问题,但是编译时,程序遇到了错误,错误提示没有定义qcout,但是定义了,猜测是生成特定类时,该类的定义没有与Worker类关联起来。有两种修改方式,一种是将两个头文件定义在queuetp.h中。另一种方法是在queue.h中包含workermi.h的头文件,这样便可以解决该问题。测试代码以Worker的测试代码为样板,稍微修改了一下,代码如下:

// definition and methods for QueueTP class
#ifndef QUEUETP_H_
#define QUEUETP_H_

#include "workermi.h"
// template class definition
template <class T>
class QueueTP
{
private:
    struct Node
    {
        T item;
        struct Node * next;
    };
    Node * front;
    Node * rear;
    enum {SIZE = 10};
    int qcount;
    int qsize;
    QueueTP(const QueueTP & q):qsize(0){}
    QueueTP & operator=(const QueueTP & q){return * this;}
public:
    QueueTP(int size = SIZE);
    ~QueueTP();
    bool isemptey() { return qcount == 0; }
    bool isfull() { return qcount == qsize; }
    bool enqueue(const T & t );
    bool dequeue(T & t);
};

// methods for QueueTP class
template <class T>
QueueTP<T>::QueueTP(int size) : qsize(size)
{
    front = rear = nullptr;
    qcount = 0;
}

template <class T>
QueueTP<T>::~QueueTP()
{
    while(qcount != 0)
    {
        Node * temp;
        temp = front;
        front = front->next;
        delete temp;
        qcount--;
    }
}

template <class T>
bool QueueTP<T>::enqueue(const T & t)
{
    if (qcount < qsize)
    {
        if (isemptey())
        {
            Node * create = new Node;
            create->item = t;
            create->next = nullptr;
            front = rear = create;
            qcount++;
            return true;
        }
        else
        {
            Node * create = new Node;
            create->item = t;
            create->next = nullptr;
            rear->next = create;
            rear = create;
            qcount++;
            return false;
        }
    }
    else
        return false;
}

template <class T>
bool QueueTP<T>::dequeue(T & t)
{
    if (qcount > 0)
    {
        Node * temp;
        t = front->item;
        temp = front;
        front = front->next;
        delete temp;
        qcount--;
        return true;
    }
    else
        return false;
}
#endif
// workermi.h -- working classes with MI
#ifndef WORKERMI_H_
#define WORKERMI_H_

#include <string>

class Worker    // an abstract base class
{
private:
    std::string fullname;
    long id;
protected:
    virtual void Data() const;
    virtual void Get();
public:
    Worker() : fullname("no one"), id(0L) {}
    Worker(const std::string & s, long n) : fullname(s), id(n) {}
    virtual ~Worker() = 0;  // pure virtual function
    virtual void Set() = 0;
    virtual void Show() const = 0;
};

class Waiter : virtual public Worker
{
private:
    int panache;
protected:
    void Data() const;
    void Get();
public:
    Waiter() : Worker(), panache(0) {}
    Waiter(const std::string & s, long n, int p = 0) : Worker(s, n), panache(p) {}
    Waiter(const Worker & wk, int p = 0) : Worker(wk), panache(p) {}
    void Set();
    void Show() const;
};

class Singer : virtual public Worker
{
protected:
    enum{other, alto, contralto, soprano,
                bass, baritone, tenor};
    enum {Vtypes = 7};
    void Data() const;
    void Get();
private:
    static char * pv[Vtypes];
    int voice;
public:
    Singer() : Worker(), voice(other) {}
    Singer(const std::string & s, long n, int v = other)
            : Worker(s, n), voice(v) {}
    Singer(const Worker & wk, int v = other) : Worker(wk), voice(v) {}
    void Set();
    void Show() const;
};

// multiple inhertitance
class SingingWaiter : public Singer, public Waiter
{
protected:
    void Data() const;
    void Get();
public:
    SingingWaiter() {}
    SingingWaiter(const std::string & s, long n, int p = 0, int v = other)
                : Worker(s, n), Waiter(s, n, p), Singer(s, n, v) {}
    SingingWaiter(const Worker & wk, int p = 0, int v = other)
                : Worker(wk), Waiter(wk, p), Singer(wk, v) {}
    SingingWaiter(const Worker & wk, int p = 0)
                : Worker(wk), Waiter(wk, p), Singer(wk) {}
    void Set();
    void Show() const;
};
#endif
// workermi11.cpp -- working class methods with MI
#include "queuetp.h"
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

// Worker methods
Worker::~Worker() {}

// protected methods
void Worker::Data() const
{
    cout << "Name: " << fullname << endl;
    cout << "Employee ID: " << id << endl;
}

void Worker::Get()
{
    getline(cin, fullname);
    cout << "Enter Woker's ID: ";
    cin >> id;
    while (cin.get() != '\n')
        continue;
}

// Waiter methods
void Waiter::Set()
{
    cout << "Enter waiter's name: ";
    Worker::Get();
    Get();
}

void Waiter::Show() const
{
    cout << "Category: waiter\n";
    Worker::Data();
    Data();
}

// protected methods
void Waiter::Data() const
{
    cout << "Panache rating: " << panache << endl;
}
void Waiter::Get()
{
    cout << "Enter the waiters's panache rating: ";
    cin >> panache;
    while (cin.get() != '\n')
        continue;
}

// Singer methods
char * Singer::pv[Vtypes] = {"other", "alto", "contralto",
        "soprano", "bass", "baritone", "tentor"};

void Singer::Set()
{
    cout << "Enter the singer's name: ";
    Worker::Get();
    Singer::Get();
}

void Singer::Show() const
{
    cout << "Category: singer\n";
    Worker::Data();
    Data();
}

// protected methods
void Singer::Data() const
{
    cout << "Vocal range: " << pv[voice] << endl;
}

void Singer::Get()
{
    cout << "Enter number for singer's vocal range:\n";
    int i;
    for (i = 0; i < Vtypes; i++)
    {
        cout << i << ": " << pv[i] << "     ";
        if (i % 4 == 3)
            cout << endl;
    }
    if (i % 4 != 0)
        cout << endl;
    cin >> voice;
    while (cin.get() != '\n')
        continue;
}

// SingingWaiter methods
void SingingWaiter::Data() const
{
    Waiter::Data();
    Singer::Data();
}

void SingingWaiter::Get()
{
    Waiter::Get();
    Singer::Get();
}

void SingingWaiter::Set()
{
    cout << "Enter singing waiter's name: ";
    Worker::Get();
    Get();
}

void SingingWaiter::Show() const
{
    cout << "Catagory: singing waiter\n";
    Worker::Data();
    Data();
}
// workmi12.cpp -- multiple inheritance
// compile with workermi.cpp
#include <iostream>
#include <cstring>
#include "queuetp.h"
const int SIZE = 5;

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

    QueueTP<Worker *> qlolas(SIZE);

    int ct;
	Worker * lolas[SIZE];
    for (ct = 0; ct < SIZE; ct++)
    {
        char choice;
        cout << "Enter the employmee catagory:\n"
             << "w: waiter  s: singer   "
             << "t: singing waiter  q: quit\n";
        cin >> choice;
        while (strchr("wstq",choice) == NULL)
        {
            cout << "Please enter a w, s, t, or q: ";
            cin >> choice;
        }
        if (choice == 'q')
            break;
        switch (choice)
        {
        case 'w': lolas[ct] = new Waiter;
				  qlolas.enqueue(lolas[ct]);
                  break;
        case 's': lolas[ct] = new Singer;
				  qlolas.enqueue(lolas[ct]);
                  break;
        case 't': lolas[ct] = new SingingWaiter;
				  qlolas.enqueue(lolas[ct]);
                  break;
        default:
            break;
        }
        cin.get();
        lolas[ct]->Set();
    }

    cout << "\nHere is your staff:\n";
    int i;
    for (i = 0; i < ct; i++)
    {
        Worker * temp;
		qlolas.dequeue(temp);
        temp->Show();
    }
    for (i = 0; i < ct; i++)
        delete lolas[i];
    cout << "Bye.\n";
    return 0;
}

运行结果如下:
image

------------恢复内容开始------------

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

typedef std::valarray\<int> ArrayInt;
typedef Pair<ArrayInt,ArrayInt> PairArray;

这样, PairArray表示的是类型Pair<std::valarray<int>,std::valarray<int>>。使用包含来实现Wine类,并用一个简单的程序对其进行测试。Wine类应该有一个默认构造函数以及如下构造函数:

// intialize label to l, number of years to y
// vintage year to yr[], bottles to bot[]
Wine(const char * l, int y, const int yr[], const int bot[]);
// intialize label to l, number of years to y
// create array objects of length y
Wine(const char * l, int y);

Wine类应该有意v额GetBottles()方法,它根据Wine对象能够存储几种年份(y),提醒用户输入年份和瓶数。方法Label放回一个指向葡萄酒名称的引用。sum()方法返回Pair对象中第二个valarray<int>对象中的瓶数总和。
测试程序应提示用户输入葡萄酒名称、元素个数以及每个元素存储的年份和瓶数等信息。程序将使用这些数据构造一个Wine对象,然后显式对象中保存的信息。
下面是一个简单的测试程序:

// pe14-1.cpp -- using Wine class with containment
#include <iostream>
#include "winec.h"

int main(void)
{
	using std::cout;
	using std::cin;
	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 array 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, intialize 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;
}

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

本题不算难,但需要对valarray对象的方法比较熟悉,类Pair的定义与本章的定义一样,在实现构造函数时,笔者忘记给years赋值了,刚开始导致程序错误,后面初始化列表赋值后正确。本题使用的valarray方法有resize(); = {yr,size_t}; operator;,样例代码如下(测试代码为题目所给代码):

// wine.h -- definition of Wine class
#ifndef WINEC_H_
#define WINEC_H_
#include <string>
#include <valarray>

// template class Pair
template<typename T1, typename T2>
class Pair
{
private:
    T1 t1;
    T2 t2;
public:
    T1 & first() { return t1; }
    T2 & second() { return t2; }
    T1 first() const { return t1; }
    T2 second() const { return t2; }
    Pair(const T1 & t1val, const T2 & t2val) : t1(t1val), t2(t2val) {}
    Pair() {};
};

typedef std::valarray<int> ArrayInt;
typedef Pair<ArrayInt, ArrayInt> PairArrayInt;

class Wine
{
private:
    std::string name;
    PairArrayInt pai;
    int years;
public:
    Wine(const char * l = "no one", int y = 0);
    Wine(const char *l, int y, const int yr[], const int bot[]);
    void GetBottles();
    const std::string & Label() const { return name; }
    int sum() const;
    void Show() const;
};

#endif
// wine.cpp -- methods for Wine class
#include <iostream>
#include "winec.h"

// constructor
Wine::Wine(const char * l, int y) : name(l), years(y)
{
    pai.first().resize(years);
    pai.second().resize(years);
}

Wine::Wine(const char *l, int y, const int yr[], const int bot[])
         : name(l), years(y)
{
    pai.first() = {yr, (long long unsigned int)years};
    pai.second() = {bot, (long long unsigned int)years};
}

// input the bottles
void Wine::GetBottles()
{
    std::cout << "Enter " << Label() << " data for " 
              << years << " year(s): " << std::endl;
    for (int i = 0; i < years; i++)
    {
        std::cout << "Enter year: ";
        std::cin >> pai.first().operator[](i);
        std::cout << "Enter bottles for that year: ";
        std::cin >> pai.second().operator[](i);
    }
    // get all '\n'
    while (std::cin.get() != '\n')
        continue;
}

int Wine::sum() const
{
    return pai.second().sum();
}

void Wine::Show() const
{
    std::cout << "Wine: " << Label() << std::endl;
    std::cout << "\t\tYear\tBottles" << std::endl; 
    for (int i = 0; i < years; i++)
        std::cout << "\t\t" << pai.first()[i] 
                  << "\t" << pai.second()[i] << std::endl;
}

// ps: Wine::years forget to intialize

运行结果如下:
image

2.采用私有继承而不是包含来完成编程练习1。同样,一些typedef可能会有所帮助,另外,您可能还需要考虑诸如下面这样的语句的含义:

PairArray::operator = (PairArray(Arrayint(),ArrayInt()));
cout << (const string &) (*this);
您设计的类应该可以使用编程练习1中的测试程序进行测试。
本题将包含的关系转换成私有继承,头文件部分修改的程序不多,类方法实现部分主要修改的是构造函数,两个构造函数采用列表初始化的方法。代码如下:

// wine.h -- definition of Wine class
#ifndef WINEC_H_
#define WINEC_H_
#include <string>
#include <valarray>

// template class Pair
template<typename T1, typename T2>
class Pair
{
private:
    T1 t1;
    T2 t2;
public:
    T1 & first() { return t1; }
    T2 & second() { return t2; }
    T1 first() const { return t1; }
    T2 second() const { return t2; }
    Pair(const T1 & t1val, const T2 & t2val) : t1(t1val), t2(t2val) {}
    Pair() {};
};

typedef std::valarray<int> ArrayInt;
typedef Pair<ArrayInt, ArrayInt> PairArrayInt;

class Wine : private std::string, private PairArrayInt
{
private:
    int years;
public:
    Wine(const char * l = "no one", int y = 0);
    Wine(const char *l, int y, const int yr[], const int bot[]);
    void GetBottles();
    const std::string & Label() const { return (const std::string &) *this; }
    int sum() const;
    void Show() const;
};

#endif
// wine.cpp -- methods for Wine class
#include <iostream>
#include "winei.h"

// constructor
Wine::Wine(const char * l, int y) : std::string(l), years(y),
Pair(ArrayInt(y),ArrayInt(y)) { }

Wine::Wine(const char *l, int y, const int yr[], const int bot[])
         : std::string(l), years(y), 
         Pair(ArrayInt{yr,(long long unsigned int)y}, ArrayInt{bot, (long long unsigned int)y}) { }

// input the bottles
void Wine::GetBottles()
{
    std::cout << "Enter " << Label() << " data for " 
              << years << " year(s): " << std::endl;
    for (int i = 0; i < years; i++)
    {
        std::cout << "Enter year: ";
        std::cin >> Pair::first().operator[](i);
        std::cout << "Enter bottles for that year: ";
        std::cin >> Pair::second().operator[](i);
    }
    // get all '\n'
    while (std::cin.get() != '\n')
        continue;
}

int Wine::sum() const
{
    return Pair::second().sum();
}

void Wine::Show() const
{
    std::cout << "Wine: " << Label() << std::endl;
    std::cout << "\t\tYear\tBottles" << std::endl; 
    for (int i = 0; i < years; i++)
        std::cout << "\t\t" << Pair::first()[i] 
                  << "\t" << Pair::second()[i] << std::endl;
}
// pe14-2.cpp -- using Wine class with inhetitance
#include <iostream>
#include "winei.h"

int main(void)
{
	using std::cout;
	using std::cin;
	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 array 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, intialize 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;
}

运行结果如下:
image

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

本题考查的是定义队列模板,同时用该队列管理指针。程序编写时没有遇到问题,但是编译时,程序遇到了错误,错误提示没有定义qcout,但是定义了,猜测是生成特定类时,该类的定义没有与Worker类关联起来。有两种修改方式,一种是将两个头文件定义在queuetp.h中。另一种方法是在queue.h中包含workermi.h的头文件,这样便可以解决该问题。测试代码以Worker的测试代码为样板,稍微修改了一下,代码如下:

// definition and methods for QueueTP class
#ifndef QUEUETP_H_
#define QUEUETP_H_

#include "workermi.h"
// template class definition
template <class T>
class QueueTP
{
private:
    struct Node
    {
        T item;
        struct Node * next;
    };
    Node * front;
    Node * rear;
    enum {SIZE = 10};
    int qcount;
    int qsize;
    QueueTP(const QueueTP & q):qsize(0){}
    QueueTP & operator=(const QueueTP & q){return * this;}
public:
    QueueTP(int size = SIZE);
    ~QueueTP();
    bool isemptey() { return qcount == 0; }
    bool isfull() { return qcount == qsize; }
    bool enqueue(const T & t );
    bool dequeue(T & t);
};

// methods for QueueTP class
template <class T>
QueueTP<T>::QueueTP(int size) : qsize(size)
{
    front = rear = nullptr;
    qcount = 0;
}

template <class T>
QueueTP<T>::~QueueTP()
{
    while(qcount != 0)
    {
        Node * temp;
        temp = front;
        front = front->next;
        delete temp;
        qcount--;
    }
}

template <class T>
bool QueueTP<T>::enqueue(const T & t)
{
    if (qcount < qsize)
    {
        if (isemptey())
        {
            Node * create = new Node;
            create->item = t;
            create->next = nullptr;
            front = rear = create;
            qcount++;
            return true;
        }
        else
        {
            Node * create = new Node;
            create->item = t;
            create->next = nullptr;
            rear->next = create;
            rear = create;
            qcount++;
            return false;
        }
    }
    else
        return false;
}

template <class T>
bool QueueTP<T>::dequeue(T & t)
{
    if (qcount > 0)
    {
        Node * temp;
        t = front->item;
        temp = front;
        front = front->next;
        delete temp;
        qcount--;
        return true;
    }
    else
        return false;
}
#endif
// workermi.h -- working classes with MI
#ifndef WORKERMI_H_
#define WORKERMI_H_

#include <string>

class Worker    // an abstract base class
{
private:
    std::string fullname;
    long id;
protected:
    virtual void Data() const;
    virtual void Get();
public:
    Worker() : fullname("no one"), id(0L) {}
    Worker(const std::string & s, long n) : fullname(s), id(n) {}
    virtual ~Worker() = 0;  // pure virtual function
    virtual void Set() = 0;
    virtual void Show() const = 0;
};

class Waiter : virtual public Worker
{
private:
    int panache;
protected:
    void Data() const;
    void Get();
public:
    Waiter() : Worker(), panache(0) {}
    Waiter(const std::string & s, long n, int p = 0) : Worker(s, n), panache(p) {}
    Waiter(const Worker & wk, int p = 0) : Worker(wk), panache(p) {}
    void Set();
    void Show() const;
};

class Singer : virtual public Worker
{
protected:
    enum{other, alto, contralto, soprano,
                bass, baritone, tenor};
    enum {Vtypes = 7};
    void Data() const;
    void Get();
private:
    static char * pv[Vtypes];
    int voice;
public:
    Singer() : Worker(), voice(other) {}
    Singer(const std::string & s, long n, int v = other)
            : Worker(s, n), voice(v) {}
    Singer(const Worker & wk, int v = other) : Worker(wk), voice(v) {}
    void Set();
    void Show() const;
};

// multiple inhertitance
class SingingWaiter : public Singer, public Waiter
{
protected:
    void Data() const;
    void Get();
public:
    SingingWaiter() {}
    SingingWaiter(const std::string & s, long n, int p = 0, int v = other)
                : Worker(s, n), Waiter(s, n, p), Singer(s, n, v) {}
    SingingWaiter(const Worker & wk, int p = 0, int v = other)
                : Worker(wk), Waiter(wk, p), Singer(wk, v) {}
    SingingWaiter(const Worker & wk, int p = 0)
                : Worker(wk), Waiter(wk, p), Singer(wk) {}
    void Set();
    void Show() const;
};
#endif
// workermi11.cpp -- working class methods with MI
#include "queuetp.h"
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

// Worker methods
Worker::~Worker() {}

// protected methods
void Worker::Data() const
{
    cout << "Name: " << fullname << endl;
    cout << "Employee ID: " << id << endl;
}

void Worker::Get()
{
    getline(cin, fullname);
    cout << "Enter Woker's ID: ";
    cin >> id;
    while (cin.get() != '\n')
        continue;
}

// Waiter methods
void Waiter::Set()
{
    cout << "Enter waiter's name: ";
    Worker::Get();
    Get();
}

void Waiter::Show() const
{
    cout << "Category: waiter\n";
    Worker::Data();
    Data();
}

// protected methods
void Waiter::Data() const
{
    cout << "Panache rating: " << panache << endl;
}
void Waiter::Get()
{
    cout << "Enter the waiters's panache rating: ";
    cin >> panache;
    while (cin.get() != '\n')
        continue;
}

// Singer methods
char * Singer::pv[Vtypes] = {"other", "alto", "contralto",
        "soprano", "bass", "baritone", "tentor"};

void Singer::Set()
{
    cout << "Enter the singer's name: ";
    Worker::Get();
    Singer::Get();
}

void Singer::Show() const
{
    cout << "Category: singer\n";
    Worker::Data();
    Data();
}

// protected methods
void Singer::Data() const
{
    cout << "Vocal range: " << pv[voice] << endl;
}

void Singer::Get()
{
    cout << "Enter number for singer's vocal range:\n";
    int i;
    for (i = 0; i < Vtypes; i++)
    {
        cout << i << ": " << pv[i] << "     ";
        if (i % 4 == 3)
            cout << endl;
    }
    if (i % 4 != 0)
        cout << endl;
    cin >> voice;
    while (cin.get() != '\n')
        continue;
}

// SingingWaiter methods
void SingingWaiter::Data() const
{
    Waiter::Data();
    Singer::Data();
}

void SingingWaiter::Get()
{
    Waiter::Get();
    Singer::Get();
}

void SingingWaiter::Set()
{
    cout << "Enter singing waiter's name: ";
    Worker::Get();
    Get();
}

void SingingWaiter::Show() const
{
    cout << "Catagory: singing waiter\n";
    Worker::Data();
    Data();
}
// workmi12.cpp -- multiple inheritance
// compile with workermi.cpp
#include <iostream>
#include <cstring>
#include "queuetp.h"
const int SIZE = 5;

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

    QueueTP<Worker *> qlolas(SIZE);

    int ct;
	Worker * lolas[SIZE];
    for (ct = 0; ct < SIZE; ct++)
    {
        char choice;
        cout << "Enter the employmee catagory:\n"
             << "w: waiter  s: singer   "
             << "t: singing waiter  q: quit\n";
        cin >> choice;
        while (strchr("wstq",choice) == NULL)
        {
            cout << "Please enter a w, s, t, or q: ";
            cin >> choice;
        }
        if (choice == 'q')
            break;
        switch (choice)
        {
        case 'w': lolas[ct] = new Waiter;
				  qlolas.enqueue(lolas[ct]);
                  break;
        case 's': lolas[ct] = new Singer;
				  qlolas.enqueue(lolas[ct]);
                  break;
        case 't': lolas[ct] = new SingingWaiter;
				  qlolas.enqueue(lolas[ct]);
                  break;
        default:
            break;
        }
        cin.get();
        lolas[ct]->Set();
    }

    cout << "\nHere is your staff:\n";
    int i;
    for (i = 0; i < ct; i++)
    {
        Worker * temp;
		qlolas.dequeue(temp);
        temp->Show();
    }
    for (i = 0; i < ct; i++)
        delete lolas[i];
    cout << "Bye.\n";
    return 0;
}

运行结果如下:
image
4.Person类保存人的名和姓。除构造函数外,它还有Show()方法,用于显式名和姓。Gunslinger类以Person类为虚基类派生而来,它包含一个Draw()成员,该方法返回一个double值,表示枪手拔枪时间。这个类还有一个int成员,表示枪手墙上的刻痕数。最后,这个类还包含一个Show()函数,用于显式所有这些信息。
PokerPlayer类以Person类虚基类派生而来。它包含一个Draw()成员,该函数返回一个1~52的随机数,用于表示扑克牌的值(也可以定义一个Card类,其中包含花色和面值成员,然后让Draw()返回一个Card对象)。PokerPlayer类使用Person类的Show()函数。请定义这些类和方法以及其他必要的方法(如用于设置对象值的方法),并使用一个类似程序清单14.12的简单程序对他们进行测试。
本题考查的是虚基类的多重继承,使用virtual就可以实现虚基类继承,定义了一个Card对象,使PokePlayer的draw()返回一个对象,代码如下:

// personmi.h -- definition Person class and using inheritance
#ifndef PERSONMI_H_
#define PERSONMI_H_
#include <string>

// class Person definition
class Person
{
private:
    std::string firstname;
    std::string lastname;
protected:
    void Get();
    void Data() const;
public:
    Person(const std::string & fn, const std::string ln) : firstname(fn), lastname(ln) { }
    Person() { }
    virtual ~Person() { }
    virtual void Set();
    virtual void Show() const = 0;
    // virtual void Draw() const;
};

class Gunslinger : virtual public Person
{
private:
    double guns;
    int noches;
protected:
    void Get();
    void Data() const;
public:
    Gunslinger() { }
    Gunslinger(const std::string & fn, const std::string ln, double g = 0.0, int n = 0) :
    Person(fn, ln), guns(g), noches(n) { }
    Gunslinger(const Person & p, double g, int n) : Person(p), guns(g), noches(n) { }
    virtual double Draw() const { return guns; }
    virtual void Set();
    virtual void Show() const;
};

class Card
{
protected:
    enum {heart, dianmond, spade, club};
    enum {CTypes = 4,PNums = 13};
private:
    static char * pc[CTypes];
    static char * pp[PNums];
    int pcolor;
    int poke;
public:
    Card();
    Card(int c, int p) : pcolor(c), poke(p) { }
    void Show() const;
};

class PokerPlayer : virtual public Person
{
private:
    Card card;
protected:
    void Get() {};
    void Data() const;
public:
    PokerPlayer() { }
    PokerPlayer(const std::string & fn, const std::string ln, const Card & c) : 
    Person(fn,ln), card(c) {}
    PokerPlayer(const Person & p, const Card & c) : Person(p), card(c) { }
    PokerPlayer(const Person & p) : Person(p){ }
    PokerPlayer(const std::string & fn, const std::string ln) : 
    Person(fn,ln) { }
    virtual Card Draw() const { Card c; return c; }
    virtual void Set();
    virtual void Show() const;
};

class BadDude : public Gunslinger, public PokerPlayer
{
public:
    BadDude() { }
    BadDude(const std::string & fn, const std::string ln, const Card & c ,double g = 0.0, int n = 0) :
    Person(fn, ln), PokerPlayer(fn, ln, c), Gunslinger(fn, ln, g, n) { }
    BadDude(const Person & p, const Card & c ,double g = 0.0, int n = 0) :
    Person(p), PokerPlayer(p, c), Gunslinger(p, g, n) { }
    BadDude(const Person & p,double g = 0.0, int n = 0) :
    Person(p), PokerPlayer(p), Gunslinger(p, g, n) { }
    virtual void Set();
    virtual void Show() const;
    double Gdraw() const;
    Card Cdraw() const;
};
#endif
// personmi.cpp -- methods for Person claa
#include <iostream>
#include <cstdlib>      // for rand() and srand()
#include <ctime>
#include "personmi.h"

using std::cin;
using std::cout;
using std::endl;
// methods for Person class
void Person::Get()
{
    cout << "Enter firstname: ";
    cin >> firstname;
    cout << "Enter lastname: ";
    cin >> lastname;
}

void Person::Data() const
{
    cout << "Name: " << lastname << ", " << firstname << endl;
}

void Person::Set()
{
    Get();
}

void Person::Show() const
{
    Data();
}

// methods for Gunlinger class
void Gunslinger::Get()
{
    cout << "Enter the seconds of taking guns: ";
    cin >> guns;
    cout << "Enter the number of noches: ";
    cin >> noches;
}
void Gunslinger::Data() const
{
    cout << "Seconds: " << guns << endl;
    cout << "Noches: " << noches << endl;
}
void Gunslinger::Set()
{
    cout << "Category gunslinger:\n";
    Person::Get();
    Get();
}
void Gunslinger::Show() const
{
    Person::Data();
    Data();
}

// methods for Card class
char * Card::pc[CTypes] = {"heart", "dianmond", "spade", "club"};
char * Card::pp[PNums] = {"A", "2", "3", "4", "5", "6", "7", "8", 
                            "9", "10", "J", "Q", "K"};
Card::Card()
{
    srand(time(0));
    pcolor = rand() % 4;
    poke = rand() % 13;
}

void Card::Show() const
{
    cout << "Card: " << pc[pcolor] << ' ' << pp[poke] << endl;
}

// methods for PokerPlayer class
void PokerPlayer::Data() const
{
    card.Show();
}

void PokerPlayer::Set()
{
    cout << "Category pokeplayer\n";
    Person::Get();
    Get();
}
void PokerPlayer::Show() const
{
    Person::Show();
    Show();
}

// methods for BadDude class
void BadDude::Set()
{
    cout << "Category baddude\n";
    Person::Get();
    Gunslinger::Get();
    PokerPlayer::Get();
}
void BadDude::Show() const
{
    Person::Data();
    Gunslinger::Data();
    PokerPlayer::Data();
}
double BadDude::Gdraw() const
{
    Gunslinger::Draw();
}
Card BadDude::Cdraw() const
{
    PokerPlayer::Draw();
}
// test Person class and using MI
// compile with personmi.cpp
#include <iostream>
#include <cstring>
#include "personmi.h"

const int SIZE = 5;
int main()
{
	using std::cout;
	using std::cin;
	using std::endl;
	Person *p[SIZE];
	int ct;
	for (ct = 0; ct < SIZE; ct++)
	{
		char choice;
		cout << "Enter the person category:\n";
		cout << "g: gunslinger	p: pokerplayer\n";
		cout << "b: baddude     q: quit\n";
		while (cin >> choice && strchr("gpbq", choice) == NULL)
			cout << "Please enter a g, p, b, q: ";
		if (choice == 'q')
			break;
		switch(choice)
		{
			case 'g' : p[ct] = new Gunslinger;
					   break;
			case 'p' : p[ct] = new PokerPlayer;
					   break;
			case 'b' : p[ct] = new BadDude;
					   break;
			default :  break;
		}
		p[ct]->Set();
	}

	for (int i = 0; i < ct; i++)
	{
		p[i]->Show();
	}
	for (int i = 0; i < ct; i++)
		delete p[i];
	cout << "Done.\n";
	return 0;
}

运行结果如下:
image

5. 下面是一些类声明:

#include <iostream>
#include <string>

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();
    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, abstr_emp & 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 SetAll() const;
};

class manager : virtual public abstr_emp
{
private:
    int inchargeof;
protected:
    int InChargeOf() 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(const abstr_emp & e, int ico);
    manager(const manager & m);
    virtual void ShowAll() const;
    virtual void SetAll() const;
};

class fink : virtual public abstr_emp
{
private:
    std::string reportsto;      // to whom fink reports
protected:
    const std::string ReportsTo() const { return reportsto; }
    const 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 fink & f);
    virtual void ShowAll() const;
    virtual void SetAll() const;
};

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

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

// pe14-5.cpp
// useemp1.cpp -- using the abstr_emp 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", "Sprindragon", "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;
}

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

abstr_emp tri[4] = {em, fi, hf, hf2};
	for (int i = 0; i < 4; i++)
		tri[i].ShowAll();

因为highfink使用的是复制构造函数,而且没有动态分配内存,因此不需要重新定义赋值运算符。
为了实现ShowAll()和SetAll()的动态联编。
定义为虚基类才可以是highfink只有一个abstr_emp实例。
highfink类的数据成员都在基类中,因此没有数据部分。
其他派生类可以通过强制向上转换使用abstr_emp的operator<<()版本。
使用这些代码,将只输出名字和工作而不输出其他信息,因为对象无法进行强制向上转换。
本题考查的是虚基类MI的定义如何写,测试代码和头文件代码如题所示,MI实现的代码如下:

// emp.cpp -- methods for mi

#include "emp.h"

using std::cout;
using std::cin;
using std::endl;
// methods for abstr_class
abstr_emp::abstr_emp() { }

abstr_emp::abstr_emp(const std::string & fn, const std::string & ln,
              const std::string & j) : fname(fn), lname(ln), job(j) { }
void abstr_emp::ShowAll() const
{
    cout << "Name: " << lname << ", " << fname << endl;
    cout << "   Job: " << job << endl;
}

void abstr_emp::SetAll()
{
    cout << "Enter firstname: ";
    cin >> fname;
    cout << "Enter lastname: ";
    cin >> lname;
    while (cin.get() != '\n')
        continue;
    cout << "Enter job: ";
    getline(cin, job);
}

std::ostream & operator<<(std::ostream & os, abstr_emp & e)
{
    os << e.lname << ", " << e.fname;
    return os;
}
abstr_emp::~abstr_emp() { }         // is necessary
// methods for employee class
employee::employee() { }
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()
{
    cout << "Category employee:\n";
    abstr_emp::SetAll();
}

// methods for employee class
manager::manager() { }
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) { }
manager::manager(const manager & m) : abstr_emp(m)
{
    inchargeof = m.inchargeof;
}

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

void manager::SetAll()
{
    cout << "Category manager:\n";
    abstr_emp::SetAll();
    cout << "Enter number of in charge of employees: ";
    cin >> inchargeof;
    while (cin.get() != '\n')
        continue;
}

// methods for fink class
fink::fink() { }
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) { }
fink::fink(const fink & f) : abstr_emp(f)
{
    reportsto = f.reportsto;
}
void fink::ShowAll() const
{
    abstr_emp::ShowAll();
    cout << "   Reports to " << reportsto << endl;
}
void fink::SetAll()
{
    cout << "Category fink:\n";
    abstr_emp::SetAll();
    cout << "Enter repeorts to : ";
    getline(cin, reportsto);
}

// methods for highfink class
highfink::highfink() { }
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 abstr_emp & e, const std::string & rpo, int ico) : 
             abstr_emp(e), manager(e, ico), fink(e, rpo) { }

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

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

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

void highfink::SetAll()
{
    cout << "Category highfink:\n";
    abstr_emp::SetAll();
    int temp_ico;
    cout << "Enter number of in charge of employees: ";
    cin >> temp_ico;
    manager::InChargeOf() = temp_ico;
    while (cin.get() != '\n')
        continue;
    std::string temp_rpo;
    cout << "Enter repeorts to : ";
    getline(cin, temp_rpo);
    fink::ReportsTo() = temp_rpo;
}

运行结果如下:
image

posted @ 2022-01-05 22:06  Fight!GO  阅读(199)  评论(0编辑  收藏  举报