《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<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章编程练习相关推荐
- C++ Primer Plus第六版第六章编程练习 第4题, 加入Benevolent Order of Programmer后,在BOP大会上
/*************************************************************************************************** ...
- C Primer Plus第六版第七章编程题目与参考答案⭐
1.编写一个程序读取输入,读到#字符停止,然后报告读取的空格数.换行符数和所有其他字符的数量. #include <stdio.h> #define STOP '#' #define SP ...
- c++ primer plus第六版第六章编程练习
编写程序读取键盘输入,回显除数字外字符,同时大写转小写,小写转大写,遇'@'就停止. //练习6.1 读取键盘输入,回显输出(除数字),另外大写字母和小写字母互转,遇"@"则退出程 ...
- C++primer plus第六版第四章编程题代码
1. #include "stdafx.h" #include <iostream> #include <string> #include <vect ...
- C Primer Plus第六版第四章编程题目与参考答案⭐
1.编写一个程序,提示用户输入名和姓,然后以"名,姓"的格式打印出来. #include <stdio.h>int main() {char firstname[20] ...
- C++ Primer Plus 第六版 所有章节课后编程练习答案
我的独立博客地址:www.blog4jimmy.com,欢迎大家关注 下面的是C++ Primer Plus 第六版所有章节的课后编程练习的答案,都是博主自己写的,有不对的地方请大家留言指出讨论讨论 ...
- 《C Primer Plus》学习笔记—第14章
目录 <C Primer Plus>学习笔记 第14章 结构和其他数据形式 1.示例问题:创建图书目录 1.程序book.c 2.建立结构声明 3.定义结构变量 1.初始化结构 2.访问结 ...
- 信安教程第二版-第14章恶意代码防范技术原理
第14章恶意代码防范技术原理 14.1 恶意代码概述 261 14.1.1 恶意代码定义与分类 261 14.1.2 恶意代码攻击模型 262 14.1.3 恶意代码生存技术 263 14.1.4 恶 ...
- C Primer Plus第六版第五章运算符,表达式,语句源码
源码 //5.1#include<stdio.h> #define ADJUST 7.31 int main(void) {const double SCALE = 0.333;doubl ...
最新文章
- 苹果曝光无人车新进展,这名华人工程师是主要贡献者
- 车辆管理系统之继续自己的任务(四)
- 如何让Moodle中所连结的flash等媒体事先呈现在画面上?
- springboot(1)使用SpringBoot基础HTTP接口GET|POST|DELETE|PUT请求
- 和合符放枕头下的作用_深度解析:记忆棉枕头好,还是乳胶枕头好?
- java除号_Java的运算符
- html 多标签页,html更多标签
- 【SQL】MERGE
- C#读写三菱Fx PLC 使用Fx 串口协议 读写Fx3U设备
- PHP User Agent
- Shiro笔记 教程
- 阿里云oss添加cdn
- matlab梯形法数值积分,数值积分(梯形法)
- 追风筝的人 第三章
- 备战双11,送你一份解压壁纸!
- 快看,他纯用css绘制出了嫦娥手捧的月兔,关键还能飞,牛
- ViewPager实现左右无限循环效果
- (1)Terminal 终端终结者——安装和使用快捷键
- settext 下划线_Android TextView 添加下划线的几种方式
- pytorch中SiLU激活函数