You are on page 1of 44

1. 1.

The Wine class has a string class object member (see Chapter 4) that holds the name of
a wine and a Pair object (as discussed in this chapter) of valarray objects (as discussed
in this chapter). The first member of each Pair object holds the vintage years,
and the second member holds the numbers of bottles owned for the corresponding particular
vintage year. For example, the first valarray object of the Pair object might hold
the years 1988, 1992, and 1996, and the second valarray object might hold the bottle
counts 24, 48, and 144. It may be convenient for Wine to have an int member that
stores the number of years. Also, some typedefs might be useful to simplify the coding:
typedef std::valarray ArrayInt;
typedef Pair PairArray;
Thus the PairArray type represents type Pair<std::valarray, std::valarray<
int> >. Implement the Wine class by using containment. The class should have a
default constructor and at least the following constructors:
// initialize label to l, number of years to y,
// vintage years to yr[], bottles to bot[]
Wine(const char * l, int y, const int yr[], const int bot[]);
// initialize label to l, number of years to y,
// create array objects of length y
Wine(const char * l, int y);
The Wine class should have a method GetBottles() that, given a Wine object with y
years, prompts the user to enter the corresponding number of vintage years and bottle
counts. A method Label() should return a reference to the wine name. A method sum()
should return the total number of bottles in the second valarray object in the
Pair object.
The program should prompt the user to enter a wine name, the number of elements of
the array, and the year and bottle count information for each array element. The program
should use this data to construct a Wine object and then display the information stored
in the object. For guidance, heres a sample test program:
// pe14-1.cpp using Wine class with containment
#include
#include winec.h
int main ( void )
{
using std::cin;
using std::cout;
using std::endl;
cout << Enter name of wine: ;
char lab[50];
cin.getline(lab, 50);
cout << Enter number of years: ;
int yrs;
cin >> yrs;
Wine holding(lab, yrs); // store label, years, give arrays yrs 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, initialize 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;
}
And heres some sample output:
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 bottles for Gushing Grape Red: 180
Bye</std::valarray
winec.h
1 #ifndef WINEC_H_
2 #define WINEC_H_
3
4 #include <iostream>
5 #include <string>
6 #include <valarray>
7

8 template <class T1, class T2>


9 class Pair
10{
11private:
12 T1 a;
13 T2 b;
14public:
15 T1 & first();
16 T2 & second();
17 T1 first() const { return a; }
18 T2 second() const { return b; }
19 Pair(const T1 & aval, const T2 & bval) : a(aval), b(bval) { }
20 Pair() {}
21};
22
23template<class T1, class T2>
24T1 & Pair<T1,T2>::first()
25{
26 return a;
27}
28
29template<class T1, class T2>
30T2 & Pair<T1,T2>::second()
31{
32 return b;
33}
34
35typedef std::valarray<int> ArrayInt;
36typedef Pair<ArrayInt, ArrayInt> PairArray;
37
38class Wine

39{
40private:
41 std::string winelabel;
42 int years;
43 PairArray bt;
44
45public:
46 Wine();
47 // initialize label to l, number of years to y,
48 // vintage years to yr[], bottles to bot[]
49 Wine(const char * l, int y, const int yr[], const int bot[]);
50 // initialize label to l, number of years to y,
51 // create array objects of length y
52 Wine(const char * l, int y);
53 void GetBottles();
54 const std::string & Label() { return winelabel; }
55 int sum() const { return bt.second().sum(); }
56 void Show() const;
57};
58
59#endif
winec.cpp
1 #include "winec.h"
2
3 Wine::Wine() : winelabel("empty"), years(0), bt(ArrayInt(),ArrayInt())
4 {
5 }
6
7 Wine::Wine(const char * l, int y, const int yr[], const int bot[]) : winelabel(l), years(y),
8 bt(ArrayInt(yr,y),ArrayInt(bot,y))
9 {

10}
11
12Wine::Wine(const char * l, int y) : winelabel(l), years(y), bt(ArrayInt(0,y),ArrayInt(0,y))
13{
14}
15
16void Wine::GetBottles()
17{
18 if (years < 1)
19

std::cout << "\nNo years to enter data for or invalid number!";

20 else
21 {
22

std::cout << "Enter " << winelabel << " data for " << years << " year(s): " << std::endl;

23

for (int i = 0; i < years; i++)

24

25

std::cout << "Enter year: ";

26

(std::cin >> bt.first()[i]).get();

27

std::cout << "Enter bottles for that year: ";

28

(std::cin >> bt.second()[i]).get();

29

30 }
31}
32
33void Wine::Show() const
34{
35 using namespace std;
36 cout << "\nWine: " << winelabel << endl;
37 cout << "\tYear";
38 cout << "\tBottles" << endl;
39 for (int i = 0; i < years; i++)
40

cout << "\t" << bt.first()[i] << "\t" << bt.second()[i] << endl;

41
}
cp14ex1.cpp
1 #include <iostream>
2 #include "winec.h"
3 int main ( void )
4 {
5

using std::cin;

using std::cout;

using std::endl;

cout << "Enter name of wine: ";

char lab[50];

10 cin.getline(lab, 50);
11 cout << "Enter number of years: ";
12 int yrs;
13 cin >> yrs;
14 Wine holding(lab, yrs); // store label, years, give arrays yrs elements
15 holding.GetBottles(); // solicit input for year, bottle count
16 holding.Show(); // display object contents
17 const int YRS = 3;
18 int y[YRS] = {1993, 1995, 1998};
19 int b[YRS] = { 48, 60, 72};
20 // create new object, initialize using data in arrays y and b
21 Wine more("Gushing Grape Red",YRS, y, b);
22 more.Show();
23 cout << "Total bottles for " << more.Label() // use Label() method
24 << ": " << more.sum() << endl; // use sum() method
25
26 // testing default copy and assignment constructors, should work fine since there are no
27dynamically allocated data members;
28 cout << "\nTesting default copy and assignment constructors: \n";

29 Wine copymore = more;


30 copymore.Show();
31 Wine test;
32 test.Show();
33 test = holding;
34 holding.Show();
35 cout << "Bye\n";
36
37 cin.get();
38 cin.get();
39 return 0;
}

2. This exercise is the same as Programming Exercise 1, except that you should use private
inheritance instead of containment. Again, a few typedefs might prove handy. Also, you
might contemplate the meaning of statements such as the following:
PairArray::operator=(PairArray(ArrayInt(),ArrayInt()));
cout << (const string &)(*this);
The class should work with the same test program as shown in Programming Exercise 1.
wine_pvt.h
1 #ifndef WINE_PVT_H_
2 #define WINE_PVT_H_
3
4 #include <iostream>
5 #include <string>
6 #include <valarray>
7
8 template <class T1, class T2>
9 class Pair
10{
11private:
12 T1 a;

13 T2 b;
14public:
15 T1 & first();
16 T2 & second();
17 T1 first() const { return a; }
18 T2 second() const { return b; }
19 Pair(const T1 & aval, const T2 & bval) : a(aval), b(bval) { }
20 Pair() {}
21};
22
23template<class T1, class T2>
24T1 & Pair<T1,T2>::first()
25{
26 return a;
27}
28
29template<class T1, class T2>
30T2 & Pair<T1,T2>::second()
31{
32 return b;
33}
34
35
36class Wine : private std::string, private Pair<std::valarray<int>, std::valarray<int>>
37{
38private:
39 typedef std::valarray<int> ArrayInt;
40 typedef Pair<ArrayInt, ArrayInt> PairArray;
41 int years;
42
43public:

44 Wine();
45 // initialize label to l, number of years to y,
46 // vintage years to yr[], bottles to bot[]
47 Wine(const char * l, int y, const int yr[], const int bot[]);
48 // initialize label to l, number of years to y,
49 // create array objects of length y
50 Wine(const char * l, int y);
51 void GetBottles();
52 const std::string & Label() { return (const std::string &)(*this); }
53 int sum() const { return PairArray::second().sum(); }
54 void Show() const;
55};
56
57#endif
wine_pvt.cpp
1 #include "wine_pvt.h"
2
3 Wine::Wine() : std::string("empty"), years(0), PairArray(ArrayInt(),ArrayInt())
4 {
5 }
6
7 Wine::Wine(const char * l, int y, const int yr[], const int bot[]) : std::string(l), years(y),
8 PairArray(ArrayInt(yr,y),ArrayInt(bot,y))
9 {
10}
11
12Wine::Wine(const char * l, int y) : std::string(l), years(y), PairArray(ArrayInt(0,y),ArrayInt(0,y))
13{
14}
15
16void Wine::GetBottles()

17{
18 if (years < 1)
19

std::cout << "\nNo years to enter data for or invalid number!";

20 else
21 {
22
std::cout << "Enter " << (const std::string)(*this) << " data for " << years << " year(s): " <<
std::endl;
23
for (int i = 0; i < years; i++)
24
{
25
std::cout << "Enter year: ";
26
(std::cin >> PairArray::first()[i]).get();
27
std::cout << "Enter bottles for that year: ";
28
(std::cin >> PairArray::second()[i]).get();
29
}
30
}
31
}
32
33
void Wine::Show() const
34
{
35
using namespace std;
36
cout << "\nWine: " << (const std::string)(*this) << endl;
37
cout << "\tYear";
38
cout << "\tBottles" << endl;
39
for (int i = 0; i < years; i++)
40
cout << "\t" << PairArray::first()[i] << "\t" << PairArray::second()[i] << endl;
41
}
cp14ex2.cpp
1 #include <iostream>
2 #include "wine_pvt.h"
3 int main ( void )

4 {
5

using std::cin;

using std::cout;

using std::endl;

cout << "Enter name of wine: ";

char lab[50];

10 cin.getline(lab, 50);
11 cout << "Enter number of years: ";
12 int yrs;
13 cin >> yrs;
14 Wine holding(lab, yrs); // store label, years, give arrays yrs elements
15 holding.GetBottles(); // solicit input for year, bottle count
16 holding.Show(); // display object contents
17 const int YRS = 3;
18 int y[YRS] = {1993, 1995, 1998};
19 int b[YRS] = { 48, 60, 72};
20 // create new object, initialize using data in arrays y and b
21 Wine more("Gushing Grape Red",YRS, y, b);
22 more.Show();
23 cout << "Total bottles for " << more.Label() // use Label() method
24 << ": " << more.sum() << endl; // use sum() method
25
26 // testing default copy and assignment constructors, should work fine since there are no
dynamically allocated data members;
27
cout << "\nTesting default copy and assignment constructors: \n";
28
Wine copymore = more;
29
copymore.Show();
30
Wine test;
31
test.Show();
32
test = holding;
33
holding.Show();
34

35 cout << "Bye\n";


36
37 cin.get();
38 cin.get();
39 return 0;
}

3. Define a QueueTp template. Test it by creating a queue of pointers-to-Worker (as defined


in Listing 14.10) and using the queue in a program similar to that in Listing 14.12.
queuetp.h
1 #ifndef QUEUETP_H_
2 #define QUEUETP_H_
3
4 template <typename Type>
5 class QueueTP
6 {
7 private:
8

// class scope definitions

// Node is a nested structure definition local to this class

10 struct Node { Type item; struct Node * next;};


11 enum {Q_SIZE = 10};
12 // private class members
13 Node * front; // pointer to front of Queue
14 Node * rear; // pointer to rear of Queue
15 int items; // current number of items in Queue
16 const int qsize; // maximum number of items in Queue
17 // preemptive definitions to prevent public copying
18 QueueTP(const QueueTP & q);
19 QueueTP & operator=(const QueueTP & q) { return *this;}
20public:
21 explicit QueueTP(int qs = Q_SIZE) : qsize(qs), front(NULL), rear(NULL), items(0) {} // create

22queue with a qs limit


23 ~QueueTP();
24 bool isempty() const;
25 bool isfull() const;
26 int queuecount() const;
27 bool enqueue(const Type &item); // add item to end
28 bool dequeue(Type &item); // remove item from front
29};
30#endif
31
32template <typename Type>
33QueueTP<typename Type>::~QueueTP()
34{
35 Node * temp;
36 while (front != NULL) // while queue is not yet empty
37 {
38

temp = front; // save address of front item

39

front = front->next;// reset pointer to next item

40

delete temp; // delete former front

41 }
42}
43
44template <typename Type>
45bool QueueTP<typename Type>::isempty() const
46{
47 return items == 0;
48}
49
50template <typename Type>
51bool QueueTP<typename Type>::isfull() const
52{

53 return items == qsize;


54}
55
56template <typename Type>
57int QueueTP<typename Type>::queuecount() const
58{
59 return items;
60}
61
62// Add item to queue
63template <typename Type>
64bool QueueTP<typename Type>::enqueue(const Type & item)
65{
66 if (isfull())
67

return false;

68 Node * add = new Node; // create node


69 if (add == NULL)
70

return false; // quit if none available

71 add->item = item; // set node pointers


72 add->next = NULL;
73 items++;
74 if (front == NULL) // if queue is empty,
75

front = add; // place item at front

76 else
77

rear->next = add; // else place at rear

78 rear = add; // have rear point to new node


79 return true;
80}
81// Place front item into item variable and remove from queue
82template <typename Type>
83bool QueueTP<typename Type>::dequeue(Type & item)

84{
85 if (front == NULL)
86

return false;

87 item = front->item; // set item to first item in queue


88 items--;
89 Node * temp = front; // save location of first item
90 front = front->next; // reset front to next item
91 delete temp; // delete former first item
92 if (items == 0)
93

rear = NULL;

94 return true;
}
workermi.h
1 // workermi.h -- working classes with MI
2 #ifndef WORKERMI_H_
3 #define WORKERMI_H_
4 #include <string>
5 class Worker // an abstract base class
6 {
7 private:
8

std::string fullname;

long id;

10protected:
11 virtual void Data() const;
12 virtual void Get();
13public:
14 Worker() : fullname("no one"), id(0L) {}
15 Worker(const std::string & s, long n) : fullname(s), id(n) {}
16 virtual ~Worker() = 0; // pure virtual function
17 virtual void Set() = 0;
18 virtual void Show() const = 0;

19 const std::string & Name() const { return fullname; } // added Name method to return fullname,
used for cout
20
const long & ID() const { return id; } // added ID method to return ID, used for cout
21
};
22
class Waiter : virtual public Worker
23
{
24
private:
25
int panache;
26
protected:
27
void Data() const;
28
void Get();
29
public:
30
Waiter() : Worker(), panache(0) {}
31
Waiter(const std::string & s, long n, int p = 0) : Worker(s, n), panache(p) {}
32
Waiter(const Worker & wk, int p = 0) : Worker(wk), panache(p) {}
33
void Set();
34
void Show() const;
35
};
36
class Singer : virtual public Worker
37
{
38
protected:
39
enum {other, alto, contralto, soprano, bass, baritone, tenor};
40
enum {Vtypes = 7};
41
void Data() const;
42
void Get();
43
private:
44
static char *pv[Vtypes]; // string equivs of voice types
45
int voice;
46
public:
47
Singer() : Worker(), voice(other) {}
48
Singer(const std::string & s, long n, int v = other) : Worker(s, n), voice(v) {}
49

50 Singer(const Worker & wk, int v = other) : Worker(wk), voice(v) {}


51 void Set();
52 void Show() const;
53};
54// multiple inheritance
55class SingingWaiter : public Singer, public Waiter
56{
57protected:
58 void Data() const;
59 void Get();
60public:
61 SingingWaiter() {}
62 SingingWaiter(const std::string & s, long n, int p = 0, int v = other) : Worker(s,n), Waiter(s, n, p),
Singer(s, n, v) {}
63
SingingWaiter(const Worker & wk, int p = 0, int v = other) : Worker(wk), Waiter(wk,p),
64
Singer(wk,v) {}
65
SingingWaiter(const Waiter & wt, int v = other) : Worker(wt),Waiter(wt), Singer(wt,v) {}
66
SingingWaiter(const Singer & wt, int p = 0) : Worker(wt),Waiter(wt,p), Singer(wt) {}
67
void Set();
68
void Show() const;
};
#endif
workermi.cpp
1

// workermi.cpp -- working class methods with MI

#include "workermi.h"

#include <iostream>

using std::cout;

using std::cin;

using std::endl;

// Worker methods

Worker::~Worker() { }

// protected methods

10 void Worker::Data() const


11 {
12

cout << "Name: " << fullname << endl;

13

cout << "Employee ID: " << id << endl;

14 }
15 void Worker::Get()
16 {
17

getline(cin, fullname);

18

cout << "Enter worker's ID: ";

19

cin >> id;

20

while (cin.get() != '\n')

21

continue;

22 }
23
24 // Waiter methods
25 void Waiter::Set()
26 {
27

cout << "Enter waiter's name: ";

28

Worker::Get();

29

Get();

30 }
31 void Waiter::Show() const
32 {
33

cout << "Category: waiter\n";

34

Worker::Data();

35

Data();

36 }
37 // protected methods
38 void Waiter::Data() const
39 {

40

cout << "Panache rating: " << panache << endl;

41 }
42 void Waiter::Get()
43 {
44

cout << "Enter waiter's panache rating: ";

45

cin >> panache;

46

while (cin.get() != '\n')

47

continue;

48 }
49 // Singer methods
50 char * Singer::pv[Singer::Vtypes] = {"other", "alto", "contralto", "soprano", "bass", "baritone",
"tenor"};
51
52
53
54

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

55

Worker::Get();

56

Get();

57
58
59
60

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

61

Worker::Data();

62

Data();

63
64
65
66
67

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

68
69
70

}
void Singer::Get()

71 {
72

cout << "Enter number for singer's vocal range:\n";

73

int i;

74

for (i = 0; i < Vtypes; i++)

75

76

cout << i << ": " << pv[i] << " ";

77

if ( i % 4 == 3)

78

cout << endl;

79

80

if (i % 4 != 0)

81

cout << '\n';

82

cin >> voice;

83

while (cin.get() != '\n')

84

continue;

85 }
86 // SingingWaiter methods
87 void SingingWaiter::Data() const
88 {
89

Singer::Data();

90

Waiter::Data();

91 }
92 void SingingWaiter::Get()
93 {
94

Waiter::Get();

95

Singer::Get();

96 }
97 void SingingWaiter::Set()
98 {
99

cout << "Enter singing waiter's name: ";

100 Worker::Get();
101 Get();

102}
103void SingingWaiter::Show() const
104{
105 cout << "Category: singing waiter\n";
106 Worker::Data();
107 Data();
}
cp14ex3.cpp
1
2
3
4
5
6

#include <iostream>
#include <cstring>
#include <cstdlib> // for rand() and srand()
#include <ctime> // for time()
#include "workermi.h"
#include "queuetp.h"

7
8

const int SIZE = 5;

const int range = 20; // simulate a range of employee answers, const value for rand(), provides
10 random #s in range of 0 - range
11 bool passedexam(int answer); // answer = if matched by rand(), a worker is removed from queue
and new one is added.
12
13
14
15
16
17
18
19
20

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

21
22
23

Worker * in[SIZE]; // array of pointers to Worker based classes


int ct;

24

for (ct = 0; ct < SIZE; ct++) // get input from user and store in Worker *

25

26

char choice;

27

cout << "Enter the employee category:\n"

28

<< "w: waiter s: singer "

29

<< "t: singing waiter q: quit\n";

30

cin >> choice;

31

while (strchr("wstq", choice) == NULL)

32

33

cout << "Please enter a w, s, t, or q: ";

34

cin >> choice;

35

36

if (choice == 'q')

37

break;

38

switch(choice)

39

40

case 'w': in[ct] = new Waiter;

41

break;

42

case 's': in[ct] = new Singer;

43

break;

44

case 't': in[ct] = new SingingWaiter;

45

break;

46

47

cin.get();

48

in[ct]->Set(); // get information about chosen worker

49

50
51
52
53
54

// QUALITY ASSURANCE EMPLOYEE EXAM, uses pointers to workers : waiters, singers, and
singingwaiters take mandatory exam
// required for continued employment. Only 1 person can take exam at a time in manager's
room.

55
56

QueueTP<Worker *> exam(ct);

57

Worker * out[SIZE];

58
59

int total_exam_mins = 0;

60

int empl_exam_mins = 1;

61

int failed = 0;

62

int passed = 0;

63

int index = 0;

64

bool correct_answer = false;

65
66
67

// Time limit for exam = 10 mins, if employee can't provide correct answer within 10 mins,
employee fails the exam.

68
69

int timelimit = 10;

70
71
72

while (!exam.isfull())
{
exam.enqueue(in[index]);

73

index++;

74
75

76
77

index = 0; // reset array index to 0

78
79

cout << "\nThe number of employees taking exam: " << exam.queuecount() << ", Exam time
limit = " << timelimit << " minutes." << endl;

80
81
82
83

while (!exam.isempty())
{

correct_answer = passedexam(10); // passedexam randomly generates a number and


84 compares to answer(argument), true if equal
85

86
87

if (correct_answer && (empl_exam_mins < timelimit) && !exam.isempty()) // Passed if


correct answer is generated
{

88
89

// and within timelimit

exam.dequeue(out[index]); // passed ? remove from queue, and move on to next


employee

90

cout << "\nPASSED! Employee [" << out[index]->Worker::Name() << ", " << out[index]91 >Worker::ID() // display info
92

<< "], exam time: " << empl_exam_mins << "minutes.";

93

empl_exam_mins = 1; // reset individual time of exam for the next employee

94

index++;

95

passed++; // increase Passed Employee count


}

96
97
98

else if (!correct_answer && (empl_exam_mins > timelimit) && !exam.isempty()) // Failed if


correct answer is not generated
{

99

// within timelimit

exam.dequeue(out[index]); // failed ? remove from queue and move on to the next


100employee
101

cout << "\nFAILED! Employee [" << out[index]->Worker::Name() << ", " << out[index]>Worker::ID()
102
103

<< "], exam time: " << empl_exam_mins << " minutes.";

104

empl_exam_mins = 1;

105

index++;

106

failed++;
}

107
108

else if (!correct_answer && !exam.isempty()) // if correct answer is not generated and time
is within the timelimit,

109
empl_exam_mins++;
110generate an answer

// move on to the next cycle (minute) and try again to

111
112

total_exam_mins++;

113 }
114 // Final examination statistics
115 cout << "\n\nTotal exam time: " << total_exam_mins << " minutes.";
116

117 cout << "\nPassed: " << passed;


118 cout << "\nFailed: " << failed;
119
120 // Employee overview, doublechecking that Worker * array of pointers contains correct
information and values
121
cout << "\n\nEmployee overview: \n\n";
122
for (int i = 0; i < ct; i++)
123
{
124
out[i]->Show(); // display info
125
delete in[i]; // delete stored pointer objects
126
cout << endl;
127
}
128
129
cout << "\nBye.";
cin.get();
cin.get();
return 0;
}

bool passedexam(int answer) // answer = if matched by rand(), a worker is removed from queue
and new one is added.
{
if ((std::rand() * range / RAND_MAX) == answer) // generate a random number influenced by
range variable, and compare to answer
return true; // return true if equal
else
return false; // false otherwise
}

4. A Person class holds the first name and the last name of a person. In addition to its constructors,
it has a Show() method that displays both names. A Gunslinger class derives
virtually from the Person class. It has a Draw() member that returns a type double value
representing a gunslingers draw time. The class also has an int member representing

the number of notches on a gunslingers gun. Finally, it has a Show() function that displays
all this information.
A PokerPlayer class derives virtually from the Person class. It has a Draw() member
that returns a random number in the range 1 through 52, representing a card value.
(Optionally, you could define a Card class with suit and face value members and use a
Card return value for Draw().) The PokerPlayer class uses the Person show() function.
The BadDude class derives publicly from the Gunslinger and PokerPlayer classes. It has
a Gdraw() member that returns a bad dudes draw time and a Cdraw() member that
returns the next card drawn. It has an appropriate Show() function. Define all these
classes and methods, along with any other necessary methods (such as methods for setting
object values) and test them in a simple program similar to that in Listing 14.12.
person.h
1 #ifndef PERSON_H_
2 #define PERSON_H_
3
4 #include <iostream>
5 #include <string>
6
7 class Card
8 {
9 private:
10 char suit; // card Suit
11 int face; // card Face value
12public:
13 Card() : suit('c'), face(2) {} // initialize suit character to first letter of Suit, and face to int value
14 Card(char st, int fc);
15 std::string getsuit() const; // getsuit returns full string name of card suit
16 int getface() const { return face; } // return int value of face with range of 1-13, 13 is Joker, or
the highest value
17
void CheckAndSet(char st, int fc); // checks for validity of values and sets the card to those
18values
19};
20
21class Person
22{

23private:
24 std::string firstname; // first
25 std::string lastname; // last
26public:
27 Person(std::string fn = "no first", std::string ln = "no last") : firstname(fn), lastname(ln) {}
28 virtual void Show() const { std::cout << firstname << " " << lastname;} // display first & last
names
29
virtual void Set();
30
virtual ~Person() {}
31
friend std::ostream & operator<<(std::ostream & os, const Person & p); // friend, display first &
32
last names, used for cout <<
33
};
34
35
class Gunslinger : virtual public Person
36
{
37
private:
38
double drawtime;
39
int notches;
40
public:
41
Gunslinger(std::string fn = "gun", std::string ln = "slinger", double drt = 1.0, int nchs = 6) :
42Person(fn, ln), drawtime(drt), notches(nchs) {}
43 Gunslinger(const Person & ps, double drt = 1.0, int nchs = 6) : Person(ps), drawtime(drt),
notches(nchs) {}
44
virtual double Draw() const { return drawtime; } // returns drawtime
45
virtual void Show() const;
46
virtual void Set();
47
virtual ~Gunslinger() {}
48
};
49
50
class PokerPlayer : virtual public Person
51
{
52
public:
53

54 PokerPlayer(std::string fn = "poker", std::string ln = "player") : Person(fn, ln) {}


55 PokerPlayer(const Person & ps) : Person(ps) {}
56 virtual Card Draw() const; // returns Card with random face and suit values
57 virtual ~PokerPlayer() {}
58};
59
60class BadDude : public Gunslinger, public PokerPlayer
61{
62public:
63 BadDude(std::string fn = "bad", std::string ln = "dude", double drt = 2.0, int nchs = 5) : Person(fn,
ln), Gunslinger(fn, ln, drt, nchs), PokerPlayer(fn, ln) {}
64
BadDude(const Person & ps, double drt, int nchs) : Person(ps), Gunslinger(ps,drt,nchs),
65
PokerPlayer(ps) {}
66
BadDude(Gunslinger & gs) : Gunslinger(gs) {}
67
virtual double Gdraw() const { return Gunslinger::Draw(); } // returns drawtime, not to confuse
with
Cdraw() method
68
virtual Card Cdraw() const { return PokerPlayer::Draw(); } // returns Card with random values
(suit + face)
virtual void Show() const { Gunslinger::Show(); }
virtual void Set() { Gunslinger::Set(); }
};

#endif
person.cpp
1 #include "person.h"
2 #include <cctype>
3 #include <ctime>
4
5 Card::Card(char st, int fc)
6 {
7
8 }

CheckAndSet(st, fc);

9
10void Card::CheckAndSet(char st, int fc) // check for valid arguments to set the card, if invalid, set
suit to clubs, and face value to 1
11
{
12
if ((tolower(st) != 'c') && (tolower(st) != 'd') && (tolower(st) != 'h') && (tolower(st) != 's'))
13
{
14
std::cout << "\nInvalid suit! The card is now set to clubs - c.";
15
suit = 'c';
16
}
17
else
18
suit = tolower(st);
19
20
21
22

if ((fc < 1) || (fc > 13))


{
std::cout << "\nInvalid face value! The new value of card is 1.";

23

face = 1;

24
25
26
27

}
else
face = fc;

28
}
29
30
std::string Card::getsuit() const // return full string of suit based on first character of suit
31
{
32
std::string tempstring;
33
if (suit == 'c')
34
tempstring = "Clubs";
35
else if (suit == 'd')
36
tempstring = "Diamonds";
37
else if (suit == 'h')
38
tempstring = "Hearts";
39

40 else
41

tempstring = "Spades";

42 return tempstring;
43}
44
45void Person::Set()
46{
47 std::cout << "\nEnter first name: ";
48 (std::cin >> firstname).get();
49 std::cout << "Enter last name: ";
50 (std::cin >> lastname).get();
51}
52
53void Gunslinger::Show() const
54{
55 Person::Show();
56 std::cout << "\nDraw time: " << drawtime << std::endl;
57 std::cout << "Gun notches: " << notches;
58}
59
60void Gunslinger::Set()
61{
62 Person::Set();
63 std::cout << "Enter draw time: ";
64 (std::cin >> drawtime).get();
65 std::cout << "Enter gun notches: ";
66 (std::cin >> notches).get();
67}
68
69Card PokerPlayer::Draw() const // returns a Card value with random face and suit values
70{

71 char tempst;
72
73 int rndface = 1+int(13*rand()/(RAND_MAX + 1.0)); // generate Card face values, from 1 to 13
74 int rndsuit = 1+int(4*rand()/(RAND_MAX + 1.0)); // generate suit value from 1 to 4: Hearts or
Diamonds or Spades or Clubs
75
76
77
78

switch(rndsuit)
{
case 1 : tempst = 'c';

79

break;

80
81

case 2 : tempst = 'd';

82

break;

83
84

case 3 : tempst = 'h';

85

break;

86
87

case 4 : tempst = 's';

88

break;

89
90

default : tempst = 'c';

91
92

93
94
}
95

return Card(tempst, rndface); // initialize and return card with random values

96
std::ostream & operator<<(std::ostream & os, const Person & p) // friend functions to display First
97
& Last for use with cout <<
98
{
99
os << p.firstname << " " << p.lastname;
return os;

}
cp14ex4.cpp
1
2
3

#include <iostream>
#include <ctime>
#include "person.h"

4
5

const int SIZE = 4;

6
7
8
9
10
11
12
13

int main()
{
using std::cin;
using std::cout;
using std::endl;
using std::strchr;
std::srand(unsigned(std::time(0)));

14
15

Person pn = Person("Guest", "Danny");

16

Gunslinger gs = Gunslinger("Gunslinger", "Jim",(1+int(8*rand()/(RAND_MAX + 1.0))),5); //


17 Gunslinger's drawtime is random
18
19
20

PokerPlayer pp = PokerPlayer("Poker player", "Mike");


BadDude bd = BadDude("Bad Dude", "Tom",(1+int(8*rand()/(RAND_MAX + 1.0))),6); // Bad
Dude's drawtime is random

21
22
23

Person * inSaloon[SIZE] = {&pn, &gs, &pp, &bd}; // array of pointers to Person based classes
int i;

24
25
26
27
28
29

cout << "Today's visitors in Saloon: " << endl;


for (i = 0; i < SIZE; i++)
{
cout << "\nVisitor #" << i+1 << ": ";

30

inSaloon[i]->Show(); // display all visitors using their own Show() method

31

cout << endl;

32

33
34

// The game between two classes that have method to draw a Card

35

Card ppCard; // Poker player's card

36

Card bdCard; // Bad Dude's card

37
38
39
40
41
42
43

std::string ppSUIT = "p"; // Poker Player's card suit, initially set to random value non-equal to
that of Bad Dude's suit, for loop purposes
std::string bdSUIT = "d"; // Bad Dude's initial card suit
int ppWINS = 0; // total # of wins for Poker Player
int bdWINS = 0; // and same for Bad Dude
int Draw = 0; // total number of Draws
int cashPRIZE = 0; // cash prize for the poker game

44
45
46
47
48
49

cout << "\n*--- THE POKER GAME BETWEEN [" << pp << "] AND [" << bd << "] BEGINS! ---*"; //
the game intro text
cout << "\nGame rounds: " << SIZE << endl; // total game rounds = SIZE
for (i = 0; i < SIZE; i++)
{
cout << "\nRound " << i+1;

50

while (ppSUIT != bdSUIT) // draw cards until Poker players and Bad Dude's card suit match
51 each other, like Diamonds = Diamonds
52

53

cashPRIZE += 10; // increase cash prize of game with every card drawing loop, + $10

54

ppCard = pp.Draw(); // get Poker Player's drawn card

55

bdCard = bd.Cdraw(); // get Bad Dude's drawn card

56

ppSUIT = ppCard.getsuit(); // get the suit

57

bdSUIT = bdCard.getsuit();

58
59
60

cout << "\nPP's card: " << ppSUIT << ", " << ppCard.getface() << ". BD's card: " << bdSUIT
<< ", " << bdCard.getface(); // display drawn cards info
cout << "\nCash prize: $" << cashPRIZE; // currenct cash prize info

61

62

cout << "\n\n=== Suit MATCH! Comparing face values: ===\n";

63
64
65

cout << pp << " drew: " << ppSUIT << ", " << ppCard.getface() << endl;// display card values
at round end when suits match each other
cout << bd << " drew: " << bdSUIT << ", " << bdCard.getface() << endl; // same here for Bad
Dude

66

if (ppCard.getface() > bdCard.getface()) // compare card face values, round is won if face
value
is bigger
67
{

68
69

cout << pp << " Wins!" << endl; // if face value of Poker Player is bigger, he wins

70

ppWINS++;

71
}

72
73
74

else if (ppCard.getface() < bdCard.getface()) // if face value of Bad Dude's card is bigger, he
wins
{

75

cout << bd << " Wins!" << endl;

76

bdWINS++;

77
}

78

else

79

80

cout << "It's a DRAW!" << endl; // otherwise it's a draw

81

Draw++;

82

cashPRIZE -= 10; // for each draw, $10 is withdrawn from total cash prize

83
}

84
85

ppSUIT = "p"; // reset SUIT loop values needed for the generation of new card values

86

bdSUIT = "d";

87
88

89
90
91

cout << "\n === THE GAME ENDED! ==" << endl; // after all rounds display the totals
cout << pp << " won " << ppWINS << " time(s)!" << endl;

92

cout << bd << " won " << bdWINS << " time(s)!" << endl;

93

cout << "Draw: " << Draw << " time(s)!" << endl;

94

if (bdWINS > ppWINS) // Who won the most times get the total cash prize

95
96

cout << bd << " walked away with cash prize of $" << cashPRIZE << endl; // if Bad Dude wins,
he takes all money and freely leaves the bar
else if (bdWINS == ppWINS)

97
98

cout << "It's a draw, two players won equal amount of games, everyone keeps their
money!"; // if nobody wins, everyone keeps their money

99

else

100

101

cout << pp << " won the cash prize of $" << cashPRIZE << endl;

102

cout << "... however, " << bd << " is bitter and won't let him get the money....!!!"; // if Poker
103Player wins, Bad Dude being a bad dude, uses gun to get the cash prize
104
105

cout << "\n...then " << gs << " comes to rescue and starts a duel with " << bd << endl;// here
Gunslinger comes to rescues and starts a duel with Bad Dude

106
if (gs.Draw() < bd.Gdraw()) // if Gunslinger drew faster (drawtime is less) then he gets Bad
107Dude on the run
cout << gs << " drew gun faster and forced " << bd << " to flee.";
else if (gs.Draw() > bd.Gdraw()) // if Bad Dude drew gun faster, Gunslinger is shot and Bad
Dude gets the money
cout << bd << " drew gun faster and shot the Gunslinger, then took all cash prize money
and ran away.";
else // otherwise, they shoot and injure each other, while Poker Player leaves the saloon
with money to avoid further trouble
cout << gs << " and " << bd << " drew guns at same time and shot each other. Cash prize is
left with winner of game.";
}

cin.get();
cin.get();
return 0;
}

5. Here are some class declarations:


// emp.h header file for abstr_emp class and children
#include
#include
class abstr_emp
{
private:
std::string fname; // abstr_emps first name
std::string lname; // abstr_emps 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, const 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();
};
class manager: virtual public abstr_emp
{
private:
int inchargeof; // number of abstr_emps managed
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();
};
class fink: virtual public abstr_emp
{
private:

std::string reportsto; // to whom fink reports


protected:
const std::string ReportsTo() const { return reportsto; }
std::string & ReportsTo(){ return reportsto; }
public:
fink();
fink(const std::string & fn, const std::string & ln,
const std::string & j, const std::string & rpo);
fink(const abstr_emp & e, const std::string & rpo);
fink(const fink & e);
virtual void ShowAll() const;
virtual void SetAll();
};
class highfink: public manager, public fink // management 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();
};
Note that the class hierarchy uses MI with a virtual base class, so keep in mind the special
rules for constructor initialization lists for that case. Also note the presence of some
protected-access methods. This simplifies the code for some of the highfink methods.
(Note, for example, that if highfink::ShowAll() simply calls fink::ShowAll() and
manager::ShowAll(), it winds up calling abstr_emp::ShowAll() twice.) Provide the
class method implementations and test the classes in a program. Here is a minimal test
program:
// pe14-5.cpp
// useemp1.cpp -- using the abstr_emp classes
#include
using namespace std;
#include emp.h
int main(void)
{
employee em(Trip, Harris, Thumper);
cout << em << endl;
em.ShowAll();
manager ma(Amorphia, Spindragon, Nuancer, 5);
cout << ma << endl;
ma.ShowAll();
fink fi(Matt, Oggs, Oiler, Juno Barr);

cout << fi << endl;


fi.ShowAll();
highfink hf(ma, Curly Kew); // recruitment?
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;
}
Why is no assignment operator defined?
Why are ShowAll() and SetAll() virtual?
Why is abstr_emp a virtual base class?
Why does the highfink class have no data section?
Why is only one version of operator<<() needed?
What would happen if the end of the program were replaced with this code?
abstr_emp tri[4] = {em, fi, hf, hf2};
for (int i = 0; i < 4; i++)
tri[i].ShowAll();
emp.h
1
2

#ifndef EMP_H_
#define EMP_H_

3
4
5

#include <iostream>
#include <string>

6
7
8
9

class abstr_emp
{
private:

10
11

std::string fname; // abstr_emps first name


std::string lname; // abstr_emps last name

std::string job;
12
public:
13
abstr_emp() : fname("empty_first"), lname("empty_last"), job("empty_job") {}
14
abstr_emp(const std::string & fn, const std::string & ln, const std::string & j) : fname(fn),

15lname(ln), job(j) {}
16 virtual void ShowAll() const; // labels and shows all data
17 virtual void SetAll(); // prompts user for values
18 friend std::ostream & operator<<(std::ostream & os, const abstr_emp & e); // just displays first
and last name
19
virtual ~abstr_emp() = 0; // virtual base class
20
};
21
22
class employee : public abstr_emp
23
{
24
public:
25
employee() : abstr_emp() {}
26
employee(const std::string & fn, const std::string & ln, const std::string & j) : abstr_emp(fn, ln, j)
27
{}
28
virtual void ShowAll() const { abstr_emp::ShowAll(); }
29
virtual void SetAll() { abstr_emp::SetAll(); }
30
};
31
32
class manager: virtual public abstr_emp
33
{
34
private:
35
int inchargeof; // number of abstr_emps managed
36
protected:
37
int InChargeOf() const { return inchargeof; } // output
38
int & InChargeOf(){ return inchargeof; } // input
39
public:
40
manager() : abstr_emp(), inchargeof(0) {}
41
manager(const std::string & fn, const std::string & ln, const std::string & j, int ico = 0) :
42abstr_emp(fn, ln, j), inchargeof(ico) {}
43 manager(const abstr_emp & e, int ico) : abstr_emp(e), inchargeof(ico) {}
44 manager(const manager & m) : abstr_emp(m), inchargeof(m.inchargeof) {}
45 virtual void ShowAll() const;

46 virtual void SetAll();


47};
48
49class fink: virtual public abstr_emp
50{
51private:
52 std::string reportsto; // to whom fink reports
53protected:
54 const std::string ReportsTo() const { return reportsto; }
55 std::string & ReportsTo() { return reportsto; }
56public:
57 fink() : abstr_emp(), reportsto("noone to report to") {}
58 fink(const std::string & fn, const std::string & ln, const std::string & j, const std::string & rpo) :
abstr_emp(fn, ln, j), reportsto(rpo) {}
59
fink(const abstr_emp & e, const std::string & rpo) : abstr_emp(e), reportsto(rpo) {}
60
fink(const fink & e) : abstr_emp(e), reportsto(e.reportsto) {}
61
virtual void ShowAll() const;
62
virtual void SetAll();
63
};
64
65
class highfink: public manager, public fink // management fink
66
{
67
public:
68
highfink() : abstr_emp(), manager(), fink() {}
69
highfink(const std::string & fn, const std::string & ln, const std::string & j, const std::string & rpo,
70
int ico) : abstr_emp(fn, ln, j), manager(fn, ln, j, ico), fink(fn, ln, j, rpo) {}
71
highfink(const abstr_emp & e, const std::string & rpo, int ico) : abstr_emp(e), manager(e, ico),
72fink(e, rpo) {}
73 highfink(const fink & f, int ico) : abstr_emp(f), fink(f), manager(f, ico) {}
74 highfink(const manager & m, const std::string & rpo) : abstr_emp(m), fink(m, rpo), manager(m)
{}
75
highfink(const highfink & h) : abstr_emp(h), manager(h), fink(h) {}
76

virtual void ShowAll() const;


virtual void SetAll();
};

#endif
emp.cpp
1 #include "emp.h"
2
3 using namespace std;
4
5 void abstr_emp::ShowAll() const
6 {
7

cout << "\nFirstname: " << fname << endl;

cout << "Lastname: " << lname << endl;

cout << "Job: " << job << endl;

10}
11
12void abstr_emp::SetAll()
13{
14 cout << "\nEnter Firstname: ";
15 getline(cin,fname);
16 cout << "Enter Lastname: ";
17 getline(cin, lname);
18 cout << "Enter Job: ";
19 getline(cin, job);
20}
21
22abstr_emp::~abstr_emp() {}
23
24std::ostream & operator<<(std::ostream & os, const abstr_emp & e)
25{

26 os << e.fname << ", " << e.lname;


27 return os;
28}
29
30void manager::ShowAll() const
31{
32 abstr_emp::ShowAll();
33 cout << "In charge of: " << inchargeof << " employees" << endl;
34}
35
36void manager::SetAll()
37{
38 abstr_emp::SetAll();
39 cout << "In charge of how many employees ? ";
40 (cin >> inchargeof).get();
41}
42
43void fink::ShowAll() const
44{
45 abstr_emp::ShowAll();
46 cout << "Reports to: " << reportsto << endl;
47}
48
49void fink::SetAll()
50{
51 abstr_emp::SetAll();
52 cout << "Enter Whom to report to: ";
53 getline(cin, reportsto);
54}
55
56void highfink::ShowAll() const

57{
58 abstr_emp::ShowAll();
59 cout << "In charge of: " << InChargeOf() << " employees" << endl;
60 cout << "Reports to: " << ReportsTo() << endl;
61}
62
63void highfink::SetAll()
64{
65 abstr_emp::SetAll();
66 cout << "In charge of how many employees ? ";
67 (cin >> InChargeOf()).get();
68 cout << "Enter Whom to report to: ";
69 getline(cin, ReportsTo());
70}
cp14ex5.cpp
1 #include <iostream>
2 #include "emp.h"
3
4 using namespace std;
5
6 int main(void)
7 {
8

employee em("Trip", "Harris", "Thumper");

cout << em << endl;

10 em.ShowAll();
11 manager ma("Amorphia", "Spindragon", "Nuancer", 5);
12 cout << ma << endl;
13 ma.ShowAll();
14 fink fi("Matt", "Oggs", "Oiler", "Juno Barr");
15 cout << fi << endl;
16 fi.ShowAll();

17 highfink hf(ma, "Curly Kew"); // recruitment?


18 hf.ShowAll();
19 cout << "Press a key for next phase:\n";
20 cin.get();
21 highfink hf2;
22 hf2.SetAll();
23 cout << "Using an abstr_emp * pointer:\n";
24 abstr_emp * tri[4] = {&em, &fi, &hf, &hf2};
25 for (int i = 0; i < 4; i++)
26 tri[i]->ShowAll();
27
28 cin.get();
29 cin.get();
30 return 0;
31}
Answers for questions in exercise 5:
1) Assignment operator is unnecessary since the default will do the job of assigning static class data
members to each other. Explicit assignment and copy constructors are needed when there are
dynamically allocated data members in the class. In case of exercise 5, there are only static data
members of the class - strings and ints.
2) ShowAll() and SetAll() are virtual because for almost every derived class they display or ask for
different information. Thus, if we use base class pointer to reference a derived class, we can use
polymorphic features, such as displaying derived classes' own ShowAll() and SetAll() methods while
using a collection of base class pointers.
3) virtual ~abstr_emp() = 0; it provides the basic common data members and methods, and has IS-A
convenient relationship with its derived classes.
4) highfink inherited all data members from previous derived classes such as manager and fink
5) Since only the information from base class needs to be displayed by using operator <<() and friend
function, any derived class is automatically downcasted to base class to be used as parameter for <<
friend function to display base class information, such as first & last names.
6) Since abstr_emp is not a pointer, it is no longer can find customized version of ShowAll() based on
pointed-to type, therefore, it will only use ShowAll() based on variable type, such as abstr_emp, thus
it will only display First & Last & Job (base class) information for all derived class pointers and
variables.

You might also like