《C++ Primer Plus》(第6版)第14章编程练习

《C++ Primer Plus》(第6版)第14章编程练习

  • 《C++ Primer Plus》(第6版)第14章编程练习
    • 1. 葡萄酒
    • 2. 私有继承
    • 3. QueueTp队列模板
    • 4. Person类和PokerPlayer类
    • 5. abstr_emp类

《C++ Primer Plus》(第6版)第14章编程练习

1. 葡萄酒

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

typedef std::valarry<int> ArrayInt;
typedef Pair<ArrayInt, ArrayInt> PairArray;

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

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

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

下面是一个简单的测试程序:

#include 
#include "winec.h"
using namespace std;

int main()
{
    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 bottle for " << more.Label()
    <<": " << more.sum() << endl;
    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: 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 Bottles
		1988 42
		1994 58
		1998 122
		2001 144
Wine: Gushing Grape  Red
		Year Bottles
		1993 48
		1995 60
		1998 72
Total bottle for Gushing Grape  Red: 180
Bye

代码:

winec.h:

#ifndef WINEC_H_
#define WINEC_H_

#include 
#include 
#include 

template <class T1, class T2>
class Pair
{
private:
    T1 a;
    T2 b;

public:
    Pair(const T1 &aval, const T2 &bval) : a(aval), b(bval) {}
    Pair() {}
    void set(const T1 &yr, const T2 &bot);
    int sum() const;
    void Show(int y) const;
};

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

class Wine
{
private:
    std::string name;
    PairArray b;
    int yrs;

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

#endif

winec.cpp:

#include 
#include 
#include 
#include "winec.h"
using namespace std;

template <class T1, class T2>
void Pair<T1, T2>::set(const T1 &yr, const T2 &bot)
{
    a = yr;
    b = bot;
}

template <class T1, class T2>
int Pair<T1, T2>::sum() const
{
    return b.sum();
}

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

Wine::Wine(const char *l, int y, const int yr[], const int bot[])
{
    name = l;
    yrs = y;
    b.set(ArrayInt(yr, yrs), ArrayInt(bot, yrs));
}

Wine::Wine(const char *l, int y)
{
    name = l;
    yrs = y;
}

void Wine::GetBottles()
{
    ArrayInt yr(yrs), bot(yrs);
    cout << "Enter " << name << " data for " << yrs << " year(s):\n";
    for (int i = 0; i < yrs; i++)
    {
        cout << "Enter year: ";
        cin >> yr[i];
        cout << "Enter bottles for that year: ";
        cin >> bot[i];
    }
    b.set(yr, bot);
}

std::string &Wine::Label()
{
    return name;
}

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

void Wine::Show() const
{
    cout << "Wine: " << name << endl;
    cout << "\t\tYear\t\tBottles\n";
    b.Show(yrs);
}

运行结果:

C:\Users\81228\Documents\Program\VScode C++ Program\chapter14\14.1>g++ winec.cpp pe14-1.cpp -o pe14-1.exe

C:\Users\81228\Documents\Program\VScode C++ Program\chapter14\14.1>pe14-1
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            Bottles
                1988            42
                1994            58
                1998            122
                2001            144
Wine: Gushing Grape Red
                Year            Bottles
                1993            48
                1995            60
                1998            72
Total bottle for Gushing Grape Red: 180
Bye

C:\Users\81228\Documents\Program\VScode C++ Program\chapter14\14.1>

2. 私有继承

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

PairArray::operator=(PairArray(ArrayInt(), ArrayInt()));
cout << (const string&)(*this);

您设计的类应该可以使用编程练习1中的测试程序进行测试。

代码:

winep.h

#ifndef WINEP_H
#define WINEP_H

#include 
#include 
#include 

template <class T1, class T2>
class Pair
{
private:
	T1 a;
	T2 b;

public:
	Pair(const T1 &aval, const T2 &bval) : a(aval), b(bval) {}
	Pair() {}
	void set(const T1 &yr, const T2 &bot);
	int sum() const;
	void Show(int y) const;
};

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

class Wine : private std::string, private PairArray
{
private:
	int yrs;

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

#endif

winep.cpp:

#include 
#include 
#include 
#include "winep.h"
using namespace std;

template <class T1, class T2>
void Pair<T1, T2>::set(const T1 &yr, const T2 &bot)
{
    a = yr;
    b = bot;
}

template <class T1, class T2>
int Pair<T1, T2>::sum() const
{
    return b.sum();
}

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

Wine::Wine(const char *l, int y, const int yr[], const int bot[]) : string(l), yrs(y), PairArray(ArrayInt(yr, y), ArrayInt(bot, y))
{
}

Wine::Wine(const char *l, int y) : string(l), yrs(y)
{
}

void Wine::GetBottles()
{
    ArrayInt yr(yrs), bot(yrs);
    cout << "Enter" << (const string &)(*this) << " data for " << yrs << " year(s):\n";
    for (int i = 0; i < yrs; i++)
    {
        cout << "Enter year: ";
        cin >> yr[i];
        cout << "Enter bottles for that year: ";
        cin >> bot[i];
    }
    PairArray::set(yr, bot);
}

string &Wine::Label()
{
    return (string &)(*this);
}

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

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

运行结果:

C:\Users\81228\Documents\Program\VScode C++ Program\chapter14\14.2>g++ winep.cpp pe14-2.cpp -o pe14-2.exe

C:\Users\81228\Documents\Program\VScode C++ Program\chapter14\14.2>pe14-2
Enter name of wine: Gully Wash
Enter number of years: 4
EnterGully 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            Bottles
                1988            42
                1994            58
                1998            122
                2001            144
Wine: Gushing Grape Red
                Year            Bottles
                1993            48
                1995            60
                1998            72
Total bottle for Gushing Grape Red: 180
Bye

C:\Users\81228\Documents\Program\VScode C++ Program\chapter14\14.2>

3. QueueTp队列模板

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

代码:

QueueTp.h:

#ifndef QUEUETP_H_
#define QUEUETP_H_

template <typename T>
class QueueTp
{
private:
    static const int LEN = 10;
    T *head;
    T *tail;
    T *data;

public:
    QueueTp(int len = LEN)
    {
        data = new T[len];
        head = tail = data;
    }
    ~QueueTp() { delete[] data; }
    bool enQueue(const T &item);
    bool deQueue(T &item);
    T newQueue() const { return *(tail - 1); }
    bool isFull() const { return tail == data + sizeof(data); }
    bool isEmpty() const { return tail == head; }
};

template <typename T>
bool QueueTp<T>::enQueue(const T &item)
{
    if (isFull())
        return false;
    *tail = item;
    tail++;
    return true;
}

template <typename T>
bool QueueTp<T>::deQueue(T &item)
{
    if (isFull())
        return false;
    item = *head;
    head++;
    return true;
}

#endif // !QUEUETP_H_

workermi.h:

#ifndef WORKERMI_H_
#define WORKERMI_H_

#include 

class Worker
{
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;
    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;
};

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 &wt, int v = other) : Worker(wt), Waiter(wt), Singer(wt, v) {}
    SingingWaiter(const Singer &wt, int p = 0) : Worker(wt), Waiter(wt, p), Singer(wt) {}
    void Set();
    void Show() const;
};
#endif // !WORKERMI_H_

workermi.cpp:

#include 
#include "workermi.h"

using std::cin;
using std::cout;
using std::endl;

Worker::~Worker() {}

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

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

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

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

void Waiter::Data() const
{
    cout << "Panache rating: " << panache << endl;
}

void Waiter::Get()
{
    cout << "Enter waiter's panache rating: ";
    cin >> panache;
    while (cin.get() != '\n')
        continue;
}

char temp1[] = "other";
char temp2[] = "alto";
char temp3[] = "contralto";
char temp4[] = "soprano";
char temp5[] = "bass";
char temp6[] = "baritone";
char temp7[] = "tenor";
char *Singer::pv[Singer::Vtypes] = {temp1, temp2, temp3, temp4, temp5, temp6, temp7};

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

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

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;
}

void SingingWaiter::Data() const
{
    Singer::Data();
    Waiter::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 << "Category: singing waiter\n";
    Worker::Data();
    Data();
}

main.cpp:

#include 
#include 
#include "workermi.h"
#include "QueueTP.h"

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

    QueueTp<Worker *> queue_worker;

    int ct;
    while (!queue_worker.isFull())
    {
        char choice;
        cout << "Enter the employee category:\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':
            queue_worker.enQueue(new Waiter);
            break;
        case 's':
            queue_worker.enQueue(new Singer);
            break;
        case 't':
            queue_worker.enQueue(new SingingWaiter);
            break;
        }
        cin.get();
        queue_worker.newQueue()->Set();
    }

    cout << "\nHere is your staff:\n";
    Worker *wrk;
    while (!queue_worker.isEmpty())
    {
        queue_worker.deQueue(wrk);
        cout << endl;
        wrk->Show();
        delete wrk;
    }
    cout << "Bye.\n";
    return 0;
}

运行结果:

C:\Users\81228\Documents\Program\VScode C++ Program\chapter14\14.3>g++ workermi.cpp main.cpp -o main

C:\Users\81228\Documents\Program\VScode C++ Program\chapter14\14.3>main
Enter the employee category:
w: waiter  s:singer  t: singing waiter  q: quit
w
Enter waiter's name: Wally Slipshod
Enter worker's ID: 1040
Enter waiter's panache rating: 4
Enter the employee category:
w: waiter  s:singer  t: singing waiter  q: quit
s
Enter singer's name: Sinclair Parma
Enter worker's ID: 1044
Enter number for singer's vocal range:
0: other  1: alto  2: contralto  3: soprano  
4: bass  5: baritone  6: tenor
5
Enter the employee category:
w: waiter  s:singer  t: singing waiter  q: quit
t
Enter singing waiter's name: Natasha Gargalova
Enter worker's ID: 1021
Enter waiter's panache rating: 6
Enter number for singer's vocal range:
0: other  1: alto  2: contralto  3: soprano
4: bass  5: baritone  6: tenor
3
Enter the employee category:
w: waiter  s:singer  t: singing waiter  q: quit
q

Here is your staff:

Category: waiter
Name: Wally Slipshod
Employee ID: 1040
Panache rating: 4

Category: singer
Name: Sinclair Parma
Employee ID: 1044
Vocal range: baritone

Category: singing waiter
Name: Natasha Gargalova
Employee ID: 1021
Vocal range: soprano
Panache rating: 6
Bye.

C:\Users\81228\Documents\Program\VScode C++ Program\chapter14\14.3>

4. Person类和PokerPlayer类

Person类保存人的名和姓。除构造函数外,它还有Show()方法,用于显示名和姓。Gunslmger类以Person类为虚基类派生而来,它包含一个Draw()成员,该方法返回一个double值,表示枪手的拔枪时间。这个类还包含一个int成员,表示枪手枪上的刻痕数。最后,这个类还包含一个Show()函数,用于显示所有这些信息。

PokerPlayer类以Person类为虚基类派生而来。它包含一个Draw()成员,该函数返回一个1~52的随机数,用于扑克牌的值(也可以用定义一个Card类,其中包含花色和面值成员,然后让Draw()返回一个Card对象)。PokerPlayer类使用Person类的show()函数。BadDude()类从Gunslinger何PokerPlayer类公有派生而来。它包含Gdraw()成员(返回坏蛋拔枪时间)和Cdraw()成员(返回下一张扑克牌),另外还有一个合适的show()函数。请定义这些类和方法以及其他必要的方法(如用于设置对象值的方法),并使用一些类似程序清单14.12的简单程序对它们进行测试。

代码:

person.h:

#ifndef PERSON_H_
#define PERSON_H_

#include 
#include 

class Person
{
private:
    std::string fname; // 名
    std::string lname; // 姓

protected:
    virtual void Data() const;
    virtual void Get();

public:
    Person() : fname("Null"), lname("Null"){};
    Person(std::string fname, std::string lname) : fname(fname), lname(lname){};
    virtual ~Person() = 0;
    virtual void Set() = 0;
    virtual void Show() const = 0;
};

class Gunslinger : virtual public Person
{
private:
    double time; // 拔枪时间
    int num;     // 枪上的刻痕数

protected:
    void Data() const;
    void Get();

public:
    Gunslinger() : Person(), time(0.0), num(0){};
    Gunslinger(std::string fn, std::string ln, double ti, int nu) : Person(fn, ln), time(ti), num(nu){};
    Gunslinger(Person &p, double ti, int nu) : Person(p), time(ti), num(nu){};
    double Draw() { return time; }
    void Set();
    void Show() const;
};

class PokerPlayer : virtual public Person
{
private:
    int card; // 扑克牌的值

protected:
    void Data() const;
    void Get();

public:
    PokerPlayer() : Person(), card(1){};
    PokerPlayer(std::string fn, std::string ln, int ca) : Person(fn, ln), card(ca){};
    PokerPlayer(Person &p, int ca) : Person(p), card(ca){};
    int Draw() { return card; }
    void Set();
    void Show() const;
};

class BadDude : public Gunslinger, public PokerPlayer
{
protected:
    void Data() const;
    void Get();

public:
    BadDude(){};
    BadDude(std::string fn, std::string ln, double ti = 0.0, int nu = 0, int ca = 1)
        : Person(fn, ln), Gunslinger(fn, ln, ti, nu), PokerPlayer(fn, ln, ca) {}
    BadDude(Person &p, double ti, int nu, int ca)
        : Person(p), Gunslinger(p, ti, nu), PokerPlayer(p, ca) {}
    BadDude(Gunslinger &gs, int ca)
        : Person(gs), Gunslinger(gs), PokerPlayer(gs, ca) {}
    BadDude(PokerPlayer &pp, double ti, int nu)
        : Person(pp), Gunslinger(pp, ti, nu), PokerPlayer(pp) {}
    double Gdraw() { return Gunslinger::Draw(); }
    int Cdraw() { return PokerPlayer::Draw(); }
    void Set();
    void Show() const;
};
#endif // !PERSON_H_

person.cpp:

#include 
#include 
#include "person.h"

using std::cin;
using std::cout;
using std::endl;
using std::string;

Person::~Person() {}

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

void Person::Get()
{
    cout << "Enter person's first name: ";
    getline(cin, fname);
    cout << "Enter person's last name: ";
    getline(cin, lname);
}

void Gunslinger::Data() const
{
    cout << "Time: " << endl;
    cout << "Num of scotch: " << endl;
}

void Gunslinger::Get()
{
    cout << "Please enter time: " << endl;
    cin >> time;
    cout << "Please enter num of scotch: " << endl;
    cin >> num;
    while (cin.get() != '\n')
        continue;
}

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

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

void PokerPlayer::Data() const
{
    cout << "Card: " << card << endl;
}

void PokerPlayer::Get()
{
    cout << "Please enter card: " << endl;
    cin >> card;
    while (cin.get() != '\n')
        continue;
}

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

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

void BadDude::Data() const
{
    Gunslinger::Data();
    PokerPlayer::Data();
}

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

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

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

main.cpp:

#include 
#include 
#include "person.h"
using namespace std;

const int SIZE = 5;

int main()
{
    Person *person[SIZE];
    int ct;

    for (ct = 0; ct < SIZE; ct++)
    {
        char choice;
        cout << "Enter the employee category: \n"
             << "g: Gunslinger p: PokerPlayer "
             << "b: BadDude   q: quit\n";
        cin >> choice;
        while (strchr("gpbq", choice) == NULL)
        {
            cout << "Please enter a g, p, b, or q: ";
            cin >> choice;
        }
        if ('q' == choice)
            break;
        switch (choice)
        {
        case 'g':
            person[ct] = new Gunslinger("Guns", "Linger", 1.2, 3);
            break;
        case 'p':
            person[ct] = new PokerPlayer("Poker", "Player", 2);
            break;
        case 'b':
            person[ct] = new BadDude("Bad", "Dude", 2.1, 5);
            break;
        }
        cin.get();
    }
    cout << "\nHere is your staff:\n";
    for (int i = 0; i < ct; i++)
    {
        cout << endl;
        person[i]->Show();
    }

    for (int i = 0; i < ct; i++)
        delete person[i];

    BadDude *badd = new BadDude("Bad", "Dude", 3.3, 12);
    cout << "Draw time: " << badd->Gdraw() << endl;
    cout << "Next card: " << badd->Cdraw() << endl;
    delete badd;

    cout << "Bye.\n";

    return 0;
}

运行结果:

C:\Users\81228\Documents\Program\VScode C++ Program\chapter14\14.4>g++ person.cpp main.cpp -o main

C:\Users\81228\Documents\Program\VScode C++ Program\chapter14\14.4>main
Enter the employee category: 
g: Gunslinger p: PokerPlayer b: BadDude   q: quit
g
Enter the employee category: 
g: Gunslinger p: PokerPlayer b: BadDude   q: quit
p
Enter the employee category: 
g: Gunslinger p: PokerPlayer b: BadDude   q: quit
b
Enter the employee category: 
g: Gunslinger p: PokerPlayer b: BadDude   q: quit
q

Here is your staff:

Category: Gunslinger
First name: Guns
Last name: Linger
Time:
Num of scotch:

Category: PokerPlayer
First name: Poker
Last name: Player
Card: 2

First name: Bad
Last name: Dude
Time:
Num of scotch:
Card: 1
Draw time: 16
Next card: 1
Bye.

C:\Users\81228\Documents\Program\VScode C++ Program\chapter14\14.4>

5. abstr_emp类

下面是一些类声明:

//emp.h
#include 
#include 

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:
    void Data() const;
    void Get();
    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:
    void Data() const;
    void Get();
    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();
};

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

//main.cpp
#include 
#include "emp.h"
using namespace std;

int main(void)
{
    employee em("Trip", "Harris", "Thumper");
    cout << em << endl;
    em.ShowAll();
    manager ma("Amorphia", "Spindragib", "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;
}

代码:

//emp.cpp
#include 
#include 
#include "emp.h"

using std::cin;
using std::cout;
using std::endl;

abstr_emp::~abstr_emp() {}

abstr_emp::abstr_emp()
{
    fname = "Null";
    lname = "Null";
    job = "Null";
}

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 << "Fullname: " << fname << endl;
    cout << "Lastname: " << lname << endl;
    cout << "Job: " << job << endl;
}

void abstr_emp::SetAll()
{
    cout << "Enter firstname: ";
    cin >> fname;
    cout << "Enter lastname: ";
    cin >> lname;
    cout << "Ente job: ";
    cin.get();
    getline(cin, job);
}

std::ostream &operator<<(std::ostream &os, const abstr_emp &e)
{
    cout << e.fname << " " << e.lname << " " << e.job << endl;
    return os; // TODO: 在此处插入 return 语句
}

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

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

void manager::Data() const
{
    cout << "Inchargeof: " << inchargeof << endl;
}

void manager::Get()
{
    cout << "Enter Inchargeof: ";
    cin >> inchargeof;
}

manager::manager() : abstr_emp()
{
    inchargeof = 0;
}

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(0)
{
}

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

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

void manager::SetAll()
{
    abstr_emp::SetAll();
    cout << "Enter inchargeof: ";
    cin >> inchargeof;
}

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

void fink::Get()
{
    cout << "Enter resportsto: ";
    cin.get();
    getline(cin, reportsto);
}

fink::fink() : abstr_emp()
{
    reportsto = "Null";
}

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 &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 << "Enter reports to: ";
    cin.get();
    getline(cin, reportsto);
}

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

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 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)
{
}

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

void highfink::ShowAll() const
{
    abstr_emp::ShowAll();
    manager::Data();
    fink::Data();
}

void highfink::SetAll()
{
    abstr_emp::SetAll();
    manager::Get();
    fink::Get();
}

运行结果:

C:\Users\81228\Documents\Program\VScode C++ Program\chapter14\14.5>g++ emp.cpp main.cpp -o main

C:\Users\81228\Documents\Program\VScode C++ Program\chapter14\14.5>main
Trip Harris Thumper

Fullname: Trip     
Lastname: Harris   
Job: Thumper
Amorphia Spindragib Nuancer

Fullname: Amorphia
Lastname: Spindragib
Job: Nuancer
Inchargeof: 5
Matt Oggs Oiler

Fullname: Matt
Lastname: Oggs
Job: Oiler
Reports to: Juno Barr
Fullname: Amorphia
Lastname: Spindragib
Job: Nuancer
Inchargeof: 5
Reportsto: Curly Kew
Press a key for next phase:

Enter firstname: Xi
Enter lastname: ye
Ente job: engineer
Enter Inchargeof: 1
Enter resportsto: Null
Using an abstr_emp * pointer:
Fullname: Trip
Lastname: Harris
Job: Thumper
Fullname: Matt
Lastname: Oggs
Job: Oiler
Reports to: Juno Barr
Fullname: Amorphia
Lastname: Spindragib
Job: Nuancer
Inchargeof: 5
Reportsto: Curly Kew
Fullname: Xi
Lastname: ye
Job: engineer
Inchargeof: 1
Reportsto: Null

为什么没有定义赋值运算符?

类中不存在指针成员,不需要深拷贝,使用默认的赋值操作即可。

为什么要将ShowAll()和SetAll()定义为虚的?

因为派生类将修改基类中setAll()与ShowAll()两个函数的行为。

为什么要将abstr_emp定义为虚基类?

虚基类使得highfink从manager和fink继承过来,只包含一个abstr_emp对象的拷贝,节省空间并避免不必要的冲突。

为什么highfink类没有数据部分?

highfink类需要的的数据成员已经包含在了它的父类中。

为什么只需要一个operator<<()版本?

因为这里只显示基类中的三个成员,派生类基类中的基类部分将自动调用基类的友元函数。

如果使用下面的代码替换程序的结尾部分,将会发生什么情况?

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

编译失败,抽象类不能实例化。可以通过将virtual ~abstr_emp() = 0改为virtual ~abstr_emp();,即将abstr_emp变成非抽象类,可编译通过,此时em, fi, hf, hf2这四个派生类对象将被强制转化为基类,所以只调用基类的ShowAll()函数。

你可能感兴趣的:(C++,c++,开发语言)