《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<std::valarry,std::valarray>。使用包含来实现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<int>对象中的瓶数总和。
测试程序应提示用户输入葡萄酒名称、元素个数以及每个元素存储的年份和瓶数等信息。程序将使用这些数据来构造一个Wine对象,然后显示对象中保存的信息。

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

#include <iostream>
#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 WashYear Bottles1988 421994 581998 1222001 144
Wine: Gushing Grape  RedYear Bottles1993 481995 601998 72
Total bottle for Gushing Grape  Red: 180
Bye

代码:

winec.h:

#ifndef WINEC_H_
#define WINEC_H_#include <iostream>
#include <string>
#include <valarray>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 <iostream>
#include <string>
#include <valarray>
#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.exeC:\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 WashYear            Bottles1988            421994            581998            1222001            144
Wine: Gushing Grape RedYear            Bottles1993            481995            601998            72
Total bottle for Gushing Grape Red: 180
ByeC:\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 <iostream>
#include <string>
#include <valarray>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 <iostream>
#include <string>
#include <valarray>
#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.exeC:\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 WashYear            Bottles1988            421994            581998            1222001            144
Wine: Gushing Grape RedYear            Bottles1993            481995            601998            72
Total bottle for Gushing Grape Red: 180
ByeC:\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 <string>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 <iostream>
#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 <iostream>
#include <cstring>
#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 mainC:\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
qHere is your staff:Category: waiter
Name: Wally Slipshod
Employee ID: 1040
Panache rating: 4Category: singer
Name: Sinclair Parma
Employee ID: 1044
Vocal range: baritoneCategory: 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 <iostream>
#include <string>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 <iostream>
#include <string>
#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 <iostream>
#include <cstring>
#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 mainC:\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
qHere is your staff:Category: Gunslinger
First name: Guns
Last name: Linger
Time:
Num of scotch:Category: PokerPlayer
First name: Poker
Last name: Player
Card: 2First 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 <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: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 <iostream>
#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 <iostream>
#include <string>
#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 mainC:\Users\81228\Documents\Program\VScode C++ Program\chapter14\14.5>main
Trip Harris ThumperFullname: Trip
Lastname: Harris
Job: Thumper
Amorphia Spindragib NuancerFullname: Amorphia
Lastname: Spindragib
Job: Nuancer
Inchargeof: 5
Matt Oggs OilerFullname: 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++ Primer Plus》(第6版)第14章编程练习相关推荐

  1. C++ Primer Plus第六版第六章编程练习 第4题, 加入Benevolent Order of Programmer后,在BOP大会上

    /*************************************************************************************************** ...

  2. C Primer Plus第六版第七章编程题目与参考答案⭐

    1.编写一个程序读取输入,读到#字符停止,然后报告读取的空格数.换行符数和所有其他字符的数量. #include <stdio.h> #define STOP '#' #define SP ...

  3. c++ primer plus第六版第六章编程练习

    编写程序读取键盘输入,回显除数字外字符,同时大写转小写,小写转大写,遇'@'就停止. //练习6.1 读取键盘输入,回显输出(除数字),另外大写字母和小写字母互转,遇"@"则退出程 ...

  4. C++primer plus第六版第四章编程题代码

    1. #include "stdafx.h" #include <iostream> #include <string> #include <vect ...

  5. C Primer Plus第六版第四章编程题目与参考答案⭐

    1.编写一个程序,提示用户输入名和姓,然后以"名,姓"的格式打印出来. #include <stdio.h>int main() {char firstname[20] ...

  6. C++ Primer Plus 第六版 所有章节课后编程练习答案

    我的独立博客地址:www.blog4jimmy.com,欢迎大家关注 下面的是C++ Primer Plus 第六版所有章节的课后编程练习的答案,都是博主自己写的,有不对的地方请大家留言指出讨论讨论 ...

  7. 《C Primer Plus》学习笔记—第14章

    目录 <C Primer Plus>学习笔记 第14章 结构和其他数据形式 1.示例问题:创建图书目录 1.程序book.c 2.建立结构声明 3.定义结构变量 1.初始化结构 2.访问结 ...

  8. 信安教程第二版-第14章恶意代码防范技术原理

    第14章恶意代码防范技术原理 14.1 恶意代码概述 261 14.1.1 恶意代码定义与分类 261 14.1.2 恶意代码攻击模型 262 14.1.3 恶意代码生存技术 263 14.1.4 恶 ...

  9. C Primer Plus第六版第五章运算符,表达式,语句源码

    源码 //5.1#include<stdio.h> #define ADJUST 7.31 int main(void) {const double SCALE = 0.333;doubl ...

最新文章

  1. 苹果曝光无人车新进展,这名华人工程师是主要贡献者
  2. 车辆管理系统之继续自己的任务(四)
  3. 如何让Moodle中所连结的flash等媒体事先呈现在画面上?
  4. springboot(1)使用SpringBoot基础HTTP接口GET|POST|DELETE|PUT请求
  5. 和合符放枕头下的作用_深度解析:记忆棉枕头好,还是乳胶枕头好?
  6. java除号_Java的运算符
  7. html 多标签页,html更多标签
  8. 【SQL】MERGE
  9. C#读写三菱Fx PLC 使用Fx 串口协议 读写Fx3U设备
  10. PHP User Agent
  11. Shiro笔记 教程
  12. 阿里云oss添加cdn
  13. matlab梯形法数值积分,数值积分(梯形法)
  14. 追风筝的人 第三章
  15. 备战双11,送你一份解压壁纸!
  16. 快看,他纯用css绘制出了嫦娥手捧的月兔,关键还能飞,牛
  17. ViewPager实现左右无限循环效果
  18. (1)Terminal 终端终结者——安装和使用快捷键
  19. settext 下划线_Android TextView 添加下划线的几种方式
  20. pytorch中SiLU激活函数

热门文章

  1. vocabularies181126
  2. C语言中char*和char[]用法区别分析
  3. 堡垒机怎么安装mysql_堡垒机安装
  4. 将数值转化为汉字人民币单位
  5. 【QT】word文档操作实例——根据word模板生成word报表
  6. 《转载》各种公司的英文翻译
  7. 【git】Git 与SVN
  8. linux shell 文件空,linux shell编程 如何判断一个文件是否为空
  9. 内存管理 -- 伙伴系统(buddy system)
  10. python反爬虫机制_盘点一些网站的反爬虫机制