// studentc.h -- defining a Student class using containment
#ifndef STUDENTC_H_
#define STUDENTC_H_
#include
#include
#include
class Student
{
private:
typedef std::valarray ArrayDb;
std::string name; // contained object
ArrayDb scores; // contained object
// private method for scores output
std::ostream & arr_out(std::ostream & os) const;
public:
Student() : name("Null Student"), scores() {}
explicit Student(const std::string & s)
: name(s), scores() {}
explicit Student(int n) : name("Nully"), scores(n) {}
Student(const std::string & s, int n)
: name(s), scores(n) {}
Student(const std::string & s, const ArrayDb & a)
: name(s), scores(a) {}
Student(const char * str, const double * pd, int n)
: name(str), scores(pd, n) {}
~Student() {}
double Average() const;
const std::string & Name() const;
double & operator[](int i);
double operator[](int i) const;
// friends
// input
friend std::istream & operator>>(std::istream & is,
Student & stu); // 1 word
friend std::istream & getline(std::istream & is,
Student & stu); // 1 line
// output
friend std::ostream & operator<<(std::ostream & os,
const Student & stu);
};
#endif
// studentc.cpp -- Student class using containment
#include "studentc.h"
using std::ostream;
using std::endl;
using std::istream;
using std::string;
//public methods
double Student::Average() const
{
if (scores.size() > 0)
return scores.sum() / scores.size();
else
return 0;
}
const string & Student::Name() const
{
return name;
}
double & Student::operator[](int i)
{
return scores[i]; // use valarray::operator[]()
}
double Student::operator[](int i) const
{
return scores[i];
}
// private method
ostream & Student::arr_out(ostream & os) const
{
int i;
int lim = scores.size();
if (lim > 0)
{
for (i = 0; i < lim; i++)
{
os << scores[i] << " ";
if (i % 5 == 4)
os << endl;
}
if (i % 5 != 0)
os << endl;
}
else
os << " empty array ";
return os;
}
// friends
// use string version of operator>>()
istream & operator>>(istream & is, Student & stu)
{
is >> stu.name;
return is;
}
// use string friend getline(ostream &, const string &)
istream & getline(istream & is, Student & stu)
{
getline(is, stu.name);
return is;
}
// use string version of operator<<()
ostream & operator<<(ostream & os, const Student & stu)
{
os << "Scores for " << stu.name << ":\n";
stu.arr_out(os); // use private method for scores
return os;
}
// use_stuc.cpp -- using a composite class
// compile with studentc.cpp
#include
#include "studentc.h"
using std::cin;
using std::cout;
using std::endl;
void set(Student & sa, int n);
const int pupils = 3;
const int quizzes = 5;
int main()
{
Student ada[pupils] =
{ Student(quizzes), Student(quizzes), Student(quizzes) };
int i;
for (i = 0; i < pupils; ++i)
set(ada[i], quizzes);
cout << "\nStudent List:\n";
for (i = 0; i < pupils; ++i)
cout << ada[i].Name() << endl;
cout << "\nResults:";
for (i = 0; i < pupils; ++i)
{
cout << endl << ada[i];
cout << "average: " << ada[i].Average() << endl;
}
cout << "Done.\n";
// cin.get();
return 0;
}
void set(Student & sa, int n)
{
cout << "Please enter the student's name: ";
getline(cin, sa);
cout << "Please enter " << n << " quiz scores:\n";
for (int i = 0; i < n; i++)
cin >> sa[i];
while (cin.get() != '\n')
continue;
}
// use_stuc.cpp -- using a composite class
// compile with studentc.cpp
#include
#include "studentc.h"
using std::cin;
using std::cout;
using std::endl;
void set(Student & sa, int n);
const int pupils = 3;
const int quizzes = 5;
int main()
{
Student ada[pupils] =
{ Student(quizzes), Student(quizzes), Student(quizzes) };
int i;
for (i = 0; i < pupils; ++i)
set(ada[i], quizzes);
cout << "\nStudent List:\n";
for (i = 0; i < pupils; ++i)
cout << ada[i].Name() << endl;
cout << "\nResults:";
for (i = 0; i < pupils; ++i)
{
cout << endl << ada[i];
cout << "average: " << ada[i].Average() << endl;
}
cout << "Done.\n";
// cin.get();
return 0;
}
void set(Student & sa, int n)
{
cout << "Please enter the student's name: ";
getline(cin, sa);
cout << "Please enter " << n << " quiz scores:\n";
for (int i = 0; i < n; i++)
cin >> sa[i];
while (cin.get() != '\n')
continue;
}
执行结果:
Please enter the student's name: Pat Roone
Please enter 5 quiz scores:
83 89 72 78 95
Please enter the student's name: Fleur O'Day
Please enter 5 quiz scores:
92 89 96 74 64
Student List:
Gil Bayts
Pat Roone
Fleur O'Day
Results:
Scores for Gil Bayts:
92 94 96 93 95
average: 94
Scores for Pat Roone:
83 89 72 78 95
average: 83.4
Scores for Fleur O'Day:
92 89 96 74 64
average: 83
Done.
// studenti.h -- defining a Student class using private inheritance
#ifndef STUDENTC_H_
#define STUDENTC_H_
#include
#include
#include
class Student : private std::string, private std::valarray
{
private:
typedef std::valarray ArrayDb;
// private method for scores output
std::ostream & arr_out(std::ostream & os) const;
public:
Student() : std::string("Null Student"), ArrayDb() {}
explicit Student(const std::string & s)
: std::string(s), ArrayDb() {}
explicit Student(int n) : std::string("Nully"), ArrayDb(n) {}
Student(const std::string & s, int n)
: std::string(s), ArrayDb(n) {}
Student(const std::string & s, const ArrayDb & a)
: std::string(s), ArrayDb(a) {}
Student(const char * str, const double * pd, int n)
: std::string(str), ArrayDb(pd, n) {}
~Student() {}
double Average() const;
double & operator[](int i);
double operator[](int i) const;
const std::string & Name() const;
// friends
// input
friend std::istream & operator>>(std::istream & is,
Student & stu); // 1 word
friend std::istream & getline(std::istream & is,
Student & stu); // 1 line
// output
friend std::ostream & operator<<(std::ostream & os,
const Student & stu);
};
#endif
// studenti.cpp -- Student class using private inheritance
#include "studenti.h"
using std::ostream;
using std::endl;
using std::istream;
using std::string;
// public methods
double Student::Average() const
{
if (ArrayDb::size() > 0)
return ArrayDb::sum() / ArrayDb::size();
else
return 0;
}
const string & Student::Name() const
{
return (const string &)*this;
}
double & Student::operator[](int i)
{
return ArrayDb::operator[](i); // use ArrayDb::operator[]()
}
double Student::operator[](int i) const
{
return ArrayDb::operator[](i);
}
// private method
ostream & Student::arr_out(ostream & os) const
{
int i;
int lim = ArrayDb::size();
if (lim > 0)
{
for (i = 0; i < lim; i++)
{
os << ArrayDb::operator[](i) << " ";
if (i % 5 == 4)
os << endl;
}
if (i % 5 != 0)
os << endl;
}
else
os << " empty array ";
return os;
}
// friends
// use String version of operator>>()
istream & operator>>(istream & is, Student & stu)
{
is >> (string &)stu;
return is;
}
// use string friend getline(ostream &, const string &)
istream & getline(istream & is, Student & stu)
{
getline(is, (string &)stu);
return is;
}
// use string version of operator<<()
ostream & operator<<(ostream & os, const Student & stu)
{
os << "Scores for " << (const string &)stu << ":\n";
stu.arr_out(os); // use private method for scores
return os;
}
// use_stui.cpp -- using a class with private inheritance
// compile with studenti.cpp
#include
#include "studenti.h"
using std::cin;
using std::cout;
using std::endl;
void set(Student & sa, int n);
const int pupils = 3;
const int quizzes = 5;
int main()
{
Student ada[pupils] =
{ Student(quizzes), Student(quizzes), Student(quizzes) };
int i;
for (i = 0; i < pupils; i++)
set(ada[i], quizzes);
cout << "\nStudent List:\n";
for (i = 0; i < pupils; ++i)
cout << ada[i].Name() << endl;
cout << "\nResults:";
for (i = 0; i < pupils; i++)
{
cout << endl << ada[i];
cout << "average: " << ada[i].Average() << endl;
}
cout << "Done.\n";
// cin.get();
return 0;
}
void set(Student & sa, int n)
{
cout << "Please enter the student's name: ";
getline(cin, sa);
cout << "Please enter " << n << " quiz scores:\n";
for (int i = 0; i < n; i++)
cin >> sa[i];
while (cin.get() != '\n')
continue;
}
执行结果:
Please enter the student's name: Pat Roone
Please enter 5 quiz scores:
83 89 72 78 95
Please enter the student's name: Fleur O'Day
Please enter 5 quiz scores:
92 89 96 74 64
Student List:
Gil Bayts
Pat Roone
Fleur O'Day
Results:
Scores for Gil Bayts:
92 94 96 93 95
average: 94
Scores for Pat Roone:
83 89 72 78 95
average: 83.4
Scores for Fleur O'Day:
92 89 96 74 64
average: 83
Done.
将 worker0.cpp中的:
char * Singer::pv[] = { "other", "alto", "contralto",
"soprano", "bass", "baritone", "tenor" };
(进行强制类型转换)修改为:
char * Singer::pv[] = {(char*)"other", (char*)"alto", (char*)"contralto",
(char*)"soprano", (char*)"bass", (char*)"baritone", (char*)"tenor"};
// worker0.h -- working classes
#ifndef WORKER0_H_
#define WORKER0_H_
#include
class Worker // an abstract base class
{
private:
std::string fullname;
long id;
public:
Worker() : fullname("no one"), id(0L) {}
Worker(const std::string & s, long n)
: fullname(s), id(n) {}
virtual ~Worker() = 0; // pure virtual destructor
virtual void Set();
virtual void Show() const;
};
class Waiter : public Worker
{
private:
int panache;
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 : public Worker
{
protected:
enum {
other, alto, contralto, soprano,
bass, baritone, tenor
};
enum { Vtypes = 7 };
private:
static char *pv[Vtypes]; // string equivs of voice types
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;
};
#endif
// worker0.cpp -- working class methods
#include "worker0.h"
#include
using std::cout;
using std::cin;
using std::endl;
// Worker methods
// must implement virtual destructor, even if pure
Worker::~Worker() {}
void Worker::Set()
{
cout << "Enter worker's name: ";
getline(cin, fullname);
cout << "Enter worker's ID: ";
cin >> id;
while (cin.get() != '\n')
continue;
}
void Worker::Show() const
{
cout << "Name: " << fullname << "\n";
cout << "Employee ID: " << id << "\n";
}
// Waiter methods
void Waiter::Set()
{
Worker::Set();
cout << "Enter waiter's panache rating: ";
cin >> panache;
while (cin.get() != '\n')
continue;
}
void Waiter::Show() const
{
cout << "Category: waiter\n";
Worker::Show();
cout << "Panache rating: " << panache << "\n";
}
// Singer methods
//char * Singer::pv[] = { "other", "alto", "contralto",
// "soprano", "bass", "baritone", "tenor" };
char * Singer::pv[] = { (char*)"other", (char*)"alto", (char*)"contralto",
(char*)"soprano", (char*)"bass", (char*)"baritone", (char*)"tenor" };
void Singer::Set()
{
Worker::Set();
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;
while (cin >> voice && (voice < 0 || voice >= Vtypes))
cout << "Please enter a value >= 0 and < " << Vtypes << endl;
while (cin.get() != '\n')
continue;
}
void Singer::Show() const
{
cout << "Category: singer\n";
Worker::Show();
cout << "Vocal range: " << pv[voice] << endl;
}
// worktest.cpp -- test worker class hierarchy
#include
#include "worker0.h"
const int LIM = 4;
int main()
{
Waiter bob("Bob Apple", 314L, 5);
Singer bev("Beverly Hills", 522L, 3);
Waiter w_temp;
Singer s_temp;
Worker * pw[LIM] = { &bob, &bev, &w_temp, &s_temp };
int i;
for (i = 2; i < LIM; i++)
pw[i]->Set();
for (i = 0; i < LIM; i++)
{
pw[i]->Show();
std::cout << std::endl;
}
// std::cin.get();
return 0;
}
执行结果:
Enter worker's name: Waldo Dropmaster
Enter worker's ID: 442
Enter waiter's panache rating: 3
Enter worker's name: Sylvie Sirenne
Enter worker's ID: 555
Enter number for singer's vocal range:
0: other 1: alto 2: contralto 3: soprano
4: bass 5: baritone 6: tenor
3
Category: waiter
Name: Bob Apple
Employee ID: 314
Panache rating: 5
Category: singer
Name: Beverly Hills
Employee ID: 522
Vocal range: soprano
Category: waiter
Name: Waldo Dropmaster
Employee ID: 442
Panache rating: 3
Category: singer
Name: Sylvie Sirenne
Employee ID: 555
Vocal range: soprano
// workermi.h -- working classes with MI
#ifndef WORKERMI_H_
#define WORKERMI_H_
#include
class Worker // an abstract base class
{
private:
std::string fullname;
long id;
protected:
virtual void Data() const;
virtual void Get();
public:
Worker() : fullname("no one"), id(0L) {}
Worker(const std::string & s, long n)
: fullname(s), id(n) {}
virtual ~Worker() = 0; // pure virtual function
virtual void Set() = 0;
virtual void Show() const = 0;
};
class Waiter : virtual public Worker
{
private:
int panache;
protected:
void Data() const;
void Get();
public:
Waiter() : Worker(), panache(0) {}
Waiter(const std::string & s, long n, int p = 0)
: Worker(s, n), panache(p) {}
Waiter(const Worker & wk, int p = 0)
: Worker(wk), panache(p) {}
void Set();
void Show() const;
};
class Singer : virtual public Worker
{
protected:
enum {
other, alto, contralto, soprano,
bass, baritone, tenor
};
enum { Vtypes = 7 };
void Data() const;
void Get();
private:
static char *pv[Vtypes]; // string equivs of voice types
int voice;
public:
Singer() : Worker(), voice(other) {}
Singer(const std::string & s, long n, int v = other)
: Worker(s, n), voice(v) {}
Singer(const Worker & wk, int v = other)
: Worker(wk), voice(v) {}
void Set();
void Show() const;
};
// multiple inheritance
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 Waiter & 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.cpp -- working class methods with MI
#include "workermi.h"
#include
using std::cout;
using std::cin;
using std::endl;
// Worker methods
Worker::~Worker() { }
// protected methods
void Worker::Data() const
{
cout << "Name: " << fullname << endl;
cout << "Employee ID: " << id << endl;
}
void Worker::Get()
{
getline(cin, fullname);
cout << "Enter worker's ID: ";
cin >> id;
while (cin.get() != '\n')
continue;
}
// Waiter methods
void Waiter::Set()
{
cout << "Enter waiter's name: ";
Worker::Get();
Get();
}
void Waiter::Show() const
{
cout << "Category: waiter\n";
Worker::Data();
Data();
}
// protected methods
void Waiter::Data() const
{
cout << "Panache rating: " << panache << endl;
}
void Waiter::Get()
{
cout << "Enter waiter's panache rating: ";
cin >> panache;
while (cin.get() != '\n')
continue;
}
// Singer methods
//char * Singer::pv[Singer::Vtypes] = { "other", "alto", "contralto",
// "soprano", "bass", "baritone", "tenor" };
char * Singer::pv[] = { (char*)"other", (char*)"alto", (char*)"contralto",
(char*)"soprano", (char*)"bass", (char*)"baritone", (char*)"tenor" };
void Singer::Set()
{
cout << "Enter singer's name: ";
Worker::Get();
Get();
}
void Singer::Show() const
{
cout << "Category: singer\n";
Worker::Data();
Data();
}
// protected methods
void Singer::Data() const
{
cout << "Vocal range: " << pv[voice] << endl;
}
void Singer::Get()
{
cout << "Enter number for singer's vocal range:\n";
int i;
for (i = 0; i < Vtypes; i++)
{
cout << i << ": " << pv[i] << " ";
if (i % 4 == 3)
cout << endl;
}
if (i % 4 != 0)
cout << '\n';
while (cin >> voice && (voice < 0 || voice >= Vtypes))
cout << "Please enter a value >= 0 and < " << Vtypes << endl;
while (cin.get() != '\n')
continue;
}
// SingingWaiter methods
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();
}
// workmi.cpp -- multiple inheritance
// compile with workermi.cpp
#include
#include
#include "workermi.h"
const int SIZE = 5;
int main()
{
using std::cin;
using std::cout;
using std::endl;
using std::strchr;
Worker * lolas[SIZE];
int ct;
for (ct = 0; ct < SIZE; ct++)
{
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': lolas[ct] = new Waiter;
break;
case 's': lolas[ct] = new Singer;
break;
case 't': lolas[ct] = new SingingWaiter;
break;
}
cin.get();
lolas[ct]->Set();
}
cout << "\nHere is your staff:\n";
int i;
for (i = 0; i < ct; i++)
{
cout << endl;
lolas[i]->Show();
}
for (i = 0; i < ct; i++)
delete lolas[i];
cout << "Bye.\n";
// cin.get();
// cin.get();
return 0;
}
执行结果:
Enter the employee category:
w: waiter s: singer t: singing waiter q: quit
w
Enter waiter's name: Wally Slipshod
Enter worker's ID: 1040
Enter waiter's panache rating: 4
Enter the employee category:
w: waiter s: singer t: singing waiter q: quit
s
Enter singer's name: Sinclair Parma
Enter worker's ID: 1044
Enter number for singer's vocal range:
0: other 1: alto 2: contralto 3: soprano
4: bass 5: baritone 6: tenor
5
Enter the employee category:
w: waiter s: singer t: singing waiter q: quit
t
Enter singing waiter's name: Natasha Gargalova
Enter worker's ID: 1021
Enter waiter's panache rating: 6
Enter number for singer's vocal range:
0: other 1: alto 2: contralto 3: soprano
4: bass 5: baritone 6: tenor
3
Enter the employee category:
w: waiter s: singer t: singing waiter q: quit
q
Here is your staff:
Category: waiter
Name: Wally Slipshod
Employee ID: 1040
Panache rating: 4
Category: singer
Name: Sinclair Parma
Employee ID: 1044
Vocal range: baritone
Category: singing waiter
Name: Natasha Gargalova
Employee ID: 1021
Vocal range: soprano
Panache rating: 6
Bye.
// stacktp.h -- a stack template
#ifndef STACKTP_H_
#define STACKTP_H_
template
class Stack
{
private:
enum { MAX = 10 }; // constant specific to class
Type items[MAX]; // holds stack items
int top; // index for top stack item
public:
Stack();
bool isempty();
bool isfull();
bool push(const Type & item); // add item to stack
bool pop(Type & item); // pop top into item
};
template
Stack::Stack()
{
top = 0;
}
template
bool Stack::isempty()
{
return top == 0;
}
template
bool Stack::isfull()
{
return top == MAX;
}
template
bool Stack::push(const Type & item)
{
if (top < MAX)
{
items[top++] = item;
return true;
}
else
return false;
}
template
bool Stack::pop(Type & item)
{
if (top > 0)
{
item = items[--top];
return true;
}
else
return false;
}
#endif
// stacktem.cpp -- testing the template stack class
#include
#include
#include
#include "stacktp.h"
using std::cin;
using std::cout;
int main()
{
Stack st; // create an empty stack
char ch;
std::string po;
cout << "Please enter A to add a purchase order,\n"
<< "P to process a PO, or Q to quit.\n";
while (cin >> ch && std::toupper(ch) != 'Q')
{
while (cin.get() != '\n')
continue;
if (!std::isalpha(ch))
{
cout << '\a';
continue;
}
switch (ch)
{
case 'A':
case 'a': cout << "Enter a PO number to add: ";
cin >> po;
if (st.isfull())
cout << "stack already full\n";
else
st.push(po);
break;
case 'P':
case 'p': if (st.isempty())
cout << "stack already empty\n";
else {
st.pop(po);
cout << "PO #" << po << " popped\n";
break;
}
}
cout << "Please enter A to add a purchase order,\n"
<< "P to process a PO, or Q to quit.\n";
}
cout << "Bye\n";
// cin.get();
// cin.get();
return 0;
}
执行结果:
Please enter A to add a purchase order,
P to process a PO, or Q to quit.
A
Enter a PO number to add: red911porsche
Please enter A to add a purchase order,
P to process a PO, or Q to quit.
A
Enter a PO number to add: blueR8audi
Please enter A to add a purchase order,
P to process a PO, or Q to quit.
A
Enter a PO number to add: silver747boeing
Please enter A to add a purchase order,
P to process a PO, or Q to quit.
P
PO #silver747boeing popped
Please enter A to add a purchase order,
P to process a PO, or Q to quit.
P
PO #blueR8audi popped
Please enter A to add a purchase order,
P to process a PO, or Q to quit.
P
PO #red911porsche popped
Please enter A to add a purchase order,
P to process a PO, or Q to quit.
P
stack already empty
Please enter A to add a purchase order,
P to process a PO, or Q to quit.
Q
Bye
// stcktp1.h -- modified Stack template
#ifndef STCKTP1_H_
#define STCKTP1_H_
template
class Stack
{
private:
enum {SIZE = 10}; // default size
int stacksize;
Type * items; // holds stack items
int top; // index for top stack item
public:
explicit Stack(int ss = SIZE);
Stack(const Stack & st);
~Stack() { delete [] items; }
bool isempty() { return top == 0; }
bool isfull() { return top == stacksize; }
bool push(const Type & item); // add item to stack
bool pop(Type & item); // pop top into item
Stack & operator=(const Stack & st);
};
template
Stack::Stack(int ss) : stacksize(ss), top(0)
{
items = new Type [stacksize];
}
template
Stack::Stack(const Stack & st)
{
stacksize = st.stacksize;
top = st.top;
items = new Type [stacksize];
for (int i = 0; i < top; i++)
items[i] = st.items[i];
}
template
bool Stack::push(const Type & item)
{
if (top < stacksize)
{
items[top++] = item;
return true;
}
else
return false;
}
template
bool Stack::pop(Type & item)
{
if (top > 0)
{
item = items[--top];
return true;
}
else
return false;
}
template
Stack & Stack::operator=(const Stack & st)
{
if (this == &st)
return *this;
delete [] items;
stacksize = st.stacksize;
top = st.top;
items = new Type [stacksize];
for (int i = 0; i < top; i++)
items[i] = st.items[i];
return *this;
}
#endif
// stkoptr1.cpp -- testing stack of pointers
#include
#include // for rand(), srand()
#include // for time()
#include "stcktp1.h"
const int Num = 10;
int main()
{
std::srand(std::time(0)); // randomize rand()
std::cout << "Please enter stack size: ";
int stacksize;
std::cin >> stacksize;
// create an empty stack with stacksize slots
Stack st(stacksize);
// in basket
const char * in[Num] = {
" 1: Hank Gilgamesh", " 2: Kiki Ishtar",
" 3: Betty Rocker", " 4: Ian Flagranti",
" 5: Wolfgang Kibble", " 6: Portia Koop",
" 7: Joy Almondo", " 8: Xaverie Paprika",
" 9: Juan Moore", "10: Misha Mache"
};
// out basket
const char * out[Num];
int processed = 0;
int nextin = 0;
while (processed < Num)
{
if (st.isempty())
st.push(in[nextin++]);
else if (st.isfull())
st.pop(out[processed++]);
else if (std::rand() % 2 && nextin < Num) // 50-50 chance
st.push(in[nextin++]);
else
st.pop(out[processed++]);
}
for (int i = 0; i < Num; i++)
std::cout << out[i] << std::endl;
std::cout << "Bye\n";
// std::cin.get();
// std::cin.get();
return 0;
}
执行结果:
Please enter stack size: 5
1: Hank Gilgamesh
4: Ian Flagranti
6: Portia Koop
8: Xaverie Paprika
9: Juan Moore
10: Misha Mache
7: Joy Almondo
5: Wolfgang Kibble
3: Betty Rocker
2: Kiki Ishtar
Bye
Please enter stack size: 5
2: Kiki Ishtar
1: Hank Gilgamesh
3: Betty Rocker
4: Ian Flagranti
6: Portia Koop
9: Juan Moore
10: Misha Mache
8: Xaverie Paprika
7: Joy Almondo
5: Wolfgang Kibble
Bye
//arraytp.h -- Array Template
#ifndef ARRAYTP_H_
#define ARRAYTP_H_
#include
#include
template
class ArrayTP
{
private:
T ar[n];
public:
ArrayTP() {};
explicit ArrayTP(const T & v);
virtual T & operator[](int i);
virtual T operator[](int i) const;
};
template
ArrayTP::ArrayTP(const T & v)
{
for (int i = 0; i < n; i++)
ar[i] = v;
}
template
T & ArrayTP::operator[](int i)
{
if (i < 0 || i >= n)
{
std::cerr << "Error in array limits: " << i
<< " is out of range\n";
std::exit(EXIT_FAILURE);
}
return ar[i];
}
template
T ArrayTP::operator[](int i) const
{
if (i < 0 || i >= n)
{
std::cerr << "Error in array limits: " << i
<< " is out of range\n";
std::exit(EXIT_FAILURE);
}
return ar[i];
}
#endif
// twod.cpp -- making a 2-d array
#include
#include "arraytp.h"
int main(void)
{
using std::cout;
using std::endl;
ArrayTP sums;
ArrayTP aves;
ArrayTP< ArrayTP, 10> twodee;
int i, j;
for (i = 0; i < 10; i++)
{
sums[i] = 0;
for (j = 0; j < 5; j++)
{
twodee[i][j] = (i + 1) * (j + 1);
sums[i] += twodee[i][j];
}
aves[i] = (double)sums[i] / 5;
}
for (i = 0; i < 10; i++)
{
for (j = 0; j < 5; j++)
{
cout.width(2);
cout << twodee[i][j] << ' ';
}
cout << ": sum = ";
cout.width(3);
cout << sums[i] << ", average = " << aves[i] << endl;
}
cout << "Done.\n";
// std::cin.get();
return 0;
}
执行结果:
1 2 3 4 5 : sum = 15, average = 3
2 4 6 8 10 : sum = 30, average = 6
3 6 9 12 15 : sum = 45, average = 9
4 8 12 16 20 : sum = 60, average = 12
5 10 15 20 25 : sum = 75, average = 15
6 12 18 24 30 : sum = 90, average = 18
7 14 21 28 35 : sum = 105, average = 21
8 16 24 32 40 : sum = 120, average = 24
9 18 27 36 45 : sum = 135, average = 27
10 20 30 40 50 : sum = 150, average = 30
Done.
// pairs.cpp -- defining and using a Pair template
#include
#include
template
class Pair
{
private:
T1 a;
T2 b;
public:
T1 & first();
T2 & second();
T1 first() const { return a; }
T2 second() const { return b; }
Pair(const T1 & aval, const T2 & bval) : a(aval), b(bval) { }
Pair() {}
};
template
T1 & Pair::first()
{
return a;
}
template
T2 & Pair::second()
{
return b;
}
int main()
{
using std::cout;
using std::endl;
using std::string;
Pair ratings[4] =
{
Pair("The Purpled Duck", 5),
Pair("Jaquie's Frisco Al Fresco", 4),
Pair("Cafe Souffle", 5),
Pair("Bertie's Eats", 3)
};
int joints = sizeof(ratings) / sizeof(Pair);
cout << joints << endl;//输出joints的值
cout << "Rating:\t Eatery\n";
for (int i = 0; i < joints; i++)
cout << ratings[i].second() << ":\t "
<< ratings[i].first() << endl;
cout << "Oops! Revised rating:\n";
ratings[3].first() = "Bertie's Fab Eats";
ratings[3].second() = 6;
cout << ratings[3].second() << ":\t "
<< ratings[3].first() << endl;
// std::cin.get();
return 0;
}
执行结果:
4
Rating: Eatery
5: The Purpled Duck
4: Jaquie's Frisco Al Fresco
5: Cafe Souffle
3: Bertie's Eats
Oops! Revised rating:
6: Bertie's Fab Eats
// tempmemb.cpp -- template members
#include
using std::cout;
using std::endl;
template
class beta
{
private:
template // nested template class member
class hold
{
private:
V val;
public:
hold(V v = 0) : val(v) {}
void show() const { cout << val << endl; }
V Value() const { return val; }
};
hold q; // template object
hold n; // template object
public:
beta(T t, int i) : q(t), n(i) {}
template // template method
U blab(U u, T t) { return (n.Value() + q.Value()) * u / t; }
void Show() const { q.show(); n.show(); }
};
int main()
{
beta guy(3.5, 3);
cout << "T was set to double\n";
guy.Show();
cout << "V was set to T, which is double, then V was set to int\n";
cout << guy.blab(10, 2.3) << endl;
cout << "U was set to int\n";
cout << guy.blab(10.0, 2.3) << endl;
cout << "U was set to double\n";
cout << "Done\n";
// std::cin.get();
return 0;
}
执行结果:
T was set to double
3.5
3
V was set to T, which is double, then V was set to int
28
U was set to int
28.2609
U was set to double
Done
// stacktp.h -- a stack template
#ifndef STACKTP_H_
#define STACKTP_H_
template
class Stack
{
private:
enum { MAX = 10 }; // constant specific to class
Type items[MAX]; // holds stack items
int top; // index for top stack item
public:
Stack();
bool isempty();
bool isfull();
bool push(const Type & item); // add item to stack
bool pop(Type & item); // pop top into item
};
template
Stack::Stack()
{
top = 0;
}
template
bool Stack::isempty()
{
return top == 0;
}
template
bool Stack::isfull()
{
return top == MAX;
}
template
bool Stack::push(const Type & item)
{
if (top < MAX)
{
items[top++] = item;
return true;
}
else
return false;
}
template
bool Stack::pop(Type & item)
{
if (top > 0)
{
item = items[--top];
return true;
}
else
return false;
}
#endif
// tempparm.cpp ?templates as parameters
#include
#include "stacktp.h"
template class Thing>
class Crab
{
private:
Thing s1;
Thing s2;
public:
Crab() {};
// assumes the thing class has push() and pop() members
bool push(int a, double x) { return s1.push(a) && s2.push(x); }
bool pop(int & a, double & x) { return s1.pop(a) && s2.pop(x); }
};
int main()
{
using std::cout;
using std::cin;
using std::endl;
Crab nebula;
// Stack must match template class thing
int ni;
double nb;
cout << "Enter int double pairs, such as 4 3.5 (0 0 to end):\n";
while (cin >> ni >> nb && ni > 0 && nb > 0)
{
if (!nebula.push(ni, nb))
break;
}
while (nebula.pop(ni, nb))
cout << ni << ", " << nb << endl;
cout << "Done.\n";
// cin.get();
// cin.get();
return 0;
}
执行结果:
Enter int double pairs, such as 4 3.5 (0 0 to end):
50 22.48
25 33.87
60 19.12
0 0
60, 19.12
25, 33.87
50, 22.48
Done.
// frnd2tmp.cpp -- template class with non-template friends
#include
using std::cout;
using std::endl;
template
class HasFriend
{
private:
T item;
static int ct;
public:
HasFriend(const T & i) : item(i) { ct++; }
~HasFriend() { ct--; }
friend void counts();
friend void reports(HasFriend &); // template parameter
};
// each specialization has its own static data member
template
int HasFriend::ct = 0;
// non-template friend to all HasFriend classes
void counts()
{
cout << "int count: " << HasFriend::ct << "; ";
cout << "double count: " << HasFriend::ct << endl;
}
// non-template friend to the HasFriend class
void reports(HasFriend & hf)
{
cout << "HasFriend: " << hf.item << endl;
}
// non-template friend to the HasFriend class
void reports(HasFriend & hf)
{
cout << "HasFriend: " << hf.item << endl;
}
int main()
{
cout << "No objects declared: ";
counts();
HasFriend hfi1(10);
cout << "After hfi1 declared: ";
counts();
HasFriend hfi2(20);
cout << "After hfi2 declared: ";
counts();
HasFriend hfdb(10.5);
cout << "After hfdb declared: ";
counts();
reports(hfi1);
reports(hfi2);
reports(hfdb);
// std::cin.get();
return 0;
}
执行结果:
No objects declared: int count: 0; double count: 0
After hfi1 declared: int count: 1; double count: 0
After hfi2 declared: int count: 2; double count: 0
After hfdb declared: int count: 2; double count: 1
HasFriend: 10
HasFriend: 20
HasFriend: 10.5
// tmp2tmp.cpp -- template friends to a template class
#include
using std::cout;
using std::endl;
// template prototypes
template void counts();
template void report(T &);
// template class
template
class HasFriendT
{
private:
TT item;
static int ct;
public:
HasFriendT(const TT & i) : item(i) { ct++; }
~HasFriendT() { ct--; }
friend void counts();
friend void report<>(HasFriendT &);
};
template
int HasFriendT::ct = 0;
// template friend functions definitions
template
void counts()
{
cout << "template size: " << sizeof(HasFriendT) << "; ";
cout << "template counts(): " << HasFriendT::ct << endl;
}
template
void report(T & hf)
{
cout << hf.item << endl;
}
int main()
{
counts();
HasFriendT hfi1(10);
HasFriendT hfi2(20);
HasFriendT hfdb(10.5);
report(hfi1); // generate report(HasFriendT &)
report(hfi2); // generate report(HasFriendT &)
report(hfdb); // generate report(HasFriendT &)
cout << "counts() output:\n";
counts();
cout << "counts() output:\n";
counts();
// std::cin.get();
return 0;
}
执行结果:
template size: 4; template counts(): 0
10
20
10.5
counts() output:
template size: 4; template counts(): 2
counts() output:
template size: 8; template counts(): 1
// manyfrnd.cpp -- unbound template friend to a template class
#include
using std::cout;
using std::endl;
template
class ManyFriend
{
private:
T item;
public:
ManyFriend(const T & i) : item(i) {}
template friend void show2(C &, D &);
};
template void show2(C & c, D & d)
{
cout << c.item << ", " << d.item << endl;
}
int main()
{
ManyFriend hfi1(10);
ManyFriend hfi2(20);
ManyFriend hfdb(10.5);
cout << "hfi1, hfi2: ";
show2(hfi1, hfi2);
cout << "hfdb, hfi2: ";
show2(hfdb, hfi2);
// std::cin.get();
return 0;
}
执行结果:
hfi1, hfi2: 10, 20
hfdb, hfi2: 10.5, 20
1. 以A栏的类为基类时,B栏的类采用公有派生还是私有派生更合适
A B class Bear
class Kitchen
class Person
class Person
class Person, class Automobile
class PolarBear
class Home
class Programmer
class HorseAndJockey
class Driver
A | B | 公有派生还是私有派生合适 |
---|---|---|
class Bear | class PolarBear | 公有派生,因为北极熊也是一种熊,is-a的关系 |
class Kitchen | class Home | 私有派生,因为家中有厨房,has-a的关系 |
class Person | class Programmer | 公有派生,因为程序员也是人,is-a的关系 |
class Person | class HorseAndJockey | 私有派生,因为马和驯马师的组合包人,has-a的关系 |
class Person, class Automobile | class Driver | 人是公有的,人与司机是is-a关系;车是私有的,车与司机是has-a的关系 |
2. 假设有下面的定义:
class Frabjous { private: char fab[20]; public: Frabjous(const char * s = "C++") : fab(s) { } virtual void tell() { cout << fab; } }; class Gloam { private: int glip; Frabjous fb; public: Gloam(int g = 0, const char * s = "C++"); Gloam(int g, const Frabjous & f); void tell(); };
假设Gloam
版本的tell()
应显示glip
和fb
的值,请为这3个Gloam
方法提供定义。
Gloam::Gloam(int g, const char* s) : glip(g), fb(s){}
Gloam::Gloam(int g, const Frabjous &f) : glip(g), fb(f){} //使用Frabjous的默认复制构造函数
void Golam::tell()
{
fb.tell();
cout << glip <
3. 假设有下面的定义:
class Frabjous { private: char fab[20]; public: Frabjous(const char * s = "C++") : fab(s) { } virtual void tell() { cout << fab; } }; class Gloam : private Frabjous{ private: int glip; public: Gloam(int g = 0, const char * s = "C++"); Gloam(int g, const Frabjous & f); void tell(); };
假设Gloam
版本的tell()
应显示glip
和fab
的值,请为这3个Gloam
方法提供定义。
Gloam::Gloam(int g, const char* s) : glip(g), Frabjous(s){}
Gloam::Gloam(int g, const Frabjous &f) : glip(g), Frabjous(f){} //使用Frabjous的默认复制构造函数
void Golam::tell()
{
Frabjous::tell();
cout << glip <
4. 假设有下面的定义,它是基于程序清单14.13中的Stack
模板和程序清单14.10中的Woker
类的:
Stack
sw;
请写出将生成的类声明。只实现类声明,不实现非内联类方法。
class Stack
{
private:
enum {MAX = 10}; // constant specific to class
Worker * items[MAX]; // holds stack items
int top; // index for top stack item
public:
Stack();
Boolean isempty();
Boolean isfull();
Boolean push(const Worker * & item); // add item to stack
Boolean pop(Worker * & item); // pop top into item
}
5. 使用本章中的模板定义对下面的内容进行定义:
string
对象数组;
double
数组栈;
指向`Worker`对象的指针的栈数组。
程序清单14.18生成了多少个模板类定义?
ArrayTP str_arr;//string对象数组
StackTP db_arr_stack;//double数组栈
ArrayTP> wkptr_ stack_arr;//指向Worker对象的指针的栈数组
程序清单14.18生成4个模板:ArrayTP
、ArrayTP
和Array
。
6. 指出虚基类与非虚基类之间的区别。
如果两条继承路线有相同的祖先,非虚基类会导致最终的派生类中包含祖先成员的两份拷贝,虚基类可以解决这种问题。
1.Wine
类有一个string
类对象成员(参见第4章)和一个Pair
对象(参见本章);其中前者用于存储葡萄酒的名称,而后者有2个valarray
对象(参见本章),这两个valarray
对象分别保存了葡萄酒的酿造年份和该年生产的瓶数。例如,Pair
的第1个valarray
对象可能为1988、1992和1996年,第2个valarray
对象可能为24、48和144瓶。Wine
最好有1个int
成员用于存储年数。另外,一些typedef
可能有助于简化编程工作:
typedef std::valarray
ArrayInt; typedef Pair PairArray;
这样,PairArray
表示Pair
。使用包含来实现Wine
类,并用一个简单的程序对其进行测试。Wine类应该有一个默认构造函数以及如下构造函数:
// 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);
Wine
类应该有一个GetBottles()
方法,它根据Wine
对象能够存储几种年份(y),提示用户输入年份和瓶数。方法Label()
返回一个指向葡萄酒名称的引用。sum()
方法返回Pair对象中第二个valarray
对象中的瓶数总和。测试程序应提示用户输入葡萄酒名称、元素个数以及每个元素存储的年份和瓶数等信息。程序将使用这些数据来构造一个Wine对象,然后显示对象中保存的信息。
下面是一个简单的测试程序:
// 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; }
下面是该程序的运行情况:
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
pair.cpp:
#ifndef PAIR_H_
#define PAIR_H_
template
class Pair {
private:
T1 t1;
T2 t2;
public:
Pair(const T1& t1, const T2& t2) : t1(t1), t2(t2) {}
Pair(const Pair& p);
T1& first();
T2& second();
T1 first() const { return t1; }
T2 second() const { return t2; }
};
template
Pair::Pair(const Pair& p) {
t1 = p.t1;
t2 = p.t2;
}
template
T1& Pair::first() {
return t1;
}
template
T2& Pair::second() {
return t2;
}
#endif // PAIR_H_
winec.h:
#ifndef WINEC_H_
#define WINEC_H_
#include
#include
#include
#include "pair.h"
class Wine {
private:
typedef std::valarray ArrayInt;
typedef Pair PairArray;
std::string label;
PairArray data;
int years_num;
public:
Wine(const char* l, int y, const int yr[], const int bot[]);
Wine(const char* l, int y);
void GetBottles();
const std::string& Label() const { return label; }
int sum() const;
void Show() const;
};
#endif // WINEC_H_
winec.cpp:
#include "winec.h"
Wine::Wine(const char* l, int y, const int yr[], const int bot[])
: label(l), years_num(y), data(ArrayInt(yr, y), ArrayInt(bot, y)) {}
Wine::Wine(const char* l, int y)
: label(l), years_num(y), data(ArrayInt(y), ArrayInt(y)) {}
void Wine::GetBottles() {
int yn = 0;
int b = 0;
std::cout << "Enter " << label << " data for " << years_num << " year(s)"
<< std::endl;
for (int i = 0; i < years_num; ++i) {
std::cout << "Enter year: ";
std::cin >> yn;
data.first()[i] = yn;
std::cout << "Enter bottles for that year: ";
std::cin >> b;
data.second()[i] = b;
}
}
int Wine::sum() const { return data.second().sum(); }
void Wine::Show() const {
std::cout << "Wine: " << label << std::endl;
std::cout << "Year "
<< " Bottles" << std::endl;
for (int i = 0; i < years_num; ++i) {
std::cout << data.second()[i] << " " << data.first()[i] << std::endl;
}
}
2. 采用私有继承而不是包含来完成编程练习1。同样,一些typedef可能会有所帮助,另外,您可能还需要考虑诸如下面这样的语句的含义:
PairArray::operator=(PairArray(ArrayInt(),ArrayInt())); cout << (const string &)(*this);
您设计的类应该可以使用编程练习1中的测试程序进行测试。
pair.cpp:
#ifndef PAIR_H_
#define PAIR_H_
template
class Pair {
private:
T1 t1;
T2 t2;
public:
Pair(const T1& t1, const T2& t2) : t1(t1), t2(t2) {}
Pair(const Pair& p);
T1& first();
T2& second();
T1 first() const { return t1; }
T2 second() const { return t2; }
};
template
Pair::Pair(const Pair& p) {
t1 = p.t1;
t2 = p.t2;
}
template
T1& Pair::first() {
return t1;
}
template
T2& Pair::second() {
return t2;
}
#endif // PAIR_H_
winec.h:
#ifndef WINEC_H_
#define WINEC_H_
#include
#include
#include
#include "pair.h"
typedef std::valarray ArrayInt;
typedef Pair PairArray;
class Wine : private std::string, private PairArray {
private:
int years_num;
public:
Wine(const char* l, int y, const int yr[], const int bot[]);
Wine(const char* l, int y);
void GetBottles();
const std::string& Label() const { return (std::string&)(*this); }
int sum() const { return PairArray::second().sum(); }
void Show() const;
};
#endif // WINEC_H_
winec.cpp:
#include "winec.h"
Wine::Wine(const char* l, int y, const int yr[], const int bot[])
: std::string(l),
years_num(y),
PairArray(ArrayInt(yr, y), ArrayInt(bot, y)) {}
Wine::Wine(const char* l, int y)
: std::string(l), years_num(y), PairArray(ArrayInt(y), ArrayInt(y)) {}
void Wine::GetBottles() {
int yn = 0;
int b = 0;
std::cout << "Enter " << Label() << " data for " << years_num << " year(s)"
<< std::endl;
for (int i = 0; i < years_num; ++i) {
std::cout << "Enter year: ";
std::cin >> yn;
PairArray::first()[i] = yn;
std::cout << "Enter bottles for that year: ";
std::cin >> b;
PairArray::second()[i] = b;
}
}
void Wine::Show() const {
std::cout << "Wine: " << Label() << std::endl;
std::cout << "Year "
<< " Bottles" << std::endl;
for (int i = 0; i < years_num; ++i) {
std::cout << PairArray::second()[i] << " " << PairArray::first()[i]
<< std::endl;
}
}
3. 定义一个QueueTp
模板。然后在一个类似于程序清单14.12的程序中创建一个指向Worker
的指针队列(参见程序清单14.10中的定义),并使用该队列来测试它。
worker.h:
#ifndef WORKER_H_
#define WORKER_H_
#include
class Worker // an abstract base class
{
private:
std::string fullname;
long id;
public:
Worker() : fullname("none"), id(0L) {}
Worker(const std::string& s, long n) : fullname(s), id(n) {}
virtual ~Worker() {}
virtual void Set();
virtual void Show() const;
};
#endif // WORKER_H_
worker.cpp:
#include "worker.h"
#include
void Worker::Set() {
std::cout << "Enter worker's name: ";
getline(std::cin, fullname);
std::cout << "Enter worker's ID: ";
std::cin >> id;
while (std::cin.get() != '\n') continue;
}
void Worker::Show() const {
std::cout << "Name: " << fullname << "\n";
std::cout << "Employee ID: " << id << "\n";
}
queueTp.h:
#ifndef QUEUETP_H_
#define QUEUETP_H_
template
class QueueTp {
private:
enum { Q_SIZE = 10 };
struct Node {
T item;
Node* next_ptr;
};
Node* front;
Node* rear;
int items;
const int qsize;
public:
QueueTp(int qs = Q_SIZE);
~QueueTp();
bool isempty() const { return items == 0; }
bool isfull() const { return items == qsize; }
int queuecount() const { return items; }
bool push(const T& item);
bool pop(T& item);
};
template
QueueTp::QueueTp(int qs) : qsize(qs) {
front = rear = nullptr;
items = 0;
}
template
QueueTp::~QueueTp() {
Node* temp;
while (front != nullptr) {
temp = front;
front = front->next_ptr;
delete temp;
}
}
template
bool QueueTp::push(const T& item) {
if (isfull()) return false;
Node* add = new Node;
if (front == nullptr) // if queue is empty
{
add->item = item;
add->next_ptr = nullptr;
front = rear = add;
} else {
add->item = item;
add->next_ptr = nullptr;
rear->next_ptr = add;
rear = add;
}
items++;
return true;
}
template
bool QueueTp::pop(T& item) {
if (isempty()) return false;
item = front->item;
Node* temp;
temp = front;
front = front->next_ptr;
delete temp;
items--;
return true;
}
#endif // QUEUETP_H_
main.cpp:
#include
#include
#include "queueTp.h"
#include "worker.h"
int main() {
using std::cin;
using std::cout;
using std::endl;
using std::strchr;
QueueTp q(3);
int count = 0;
Worker* pWorker = new Worker[3];
pWorker[0] = Worker("Jack", 000001);
pWorker[1] = Worker("Toou", 000002);
pWorker[2] = Worker("Boub", 000003);
while (q.queuecount() < 3) {
pWorker[count].Show();
q.push(pWorker[count++]);
}
if (q.queuecount() == 3)
std::cout << "The Queue is full, the elements are: \n";
while (q.queuecount() > 0) {
pWorker[--count].Show();
q.pop(pWorker[count]);
}
if (q.queuecount() == 0) std::cout << "The Queue is empty now. \n";
delete[] pWorker;
return 0;
}
4. Person
类保存人的名和姓。除构造函数外,它还有Show()
方法,用于显示名和姓。Gunslinger
类以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
class Person {
private:
std::string firstname;
std::string lastname;
protected:
virtual void Data() const;
public:
Person(const char* fn = "none", const char* ln = "none")
: firstname(fn), lastname(ln) {}
// no explicit copy constructor function
virtual ~Person() {}
virtual void Show() const;
virtual void Set();
};
#endif // PERSON_H_
person.cpp:
#include "person.h"
#include
void Person::Data() const {
std::cout << firstname << ", " << lastname << std::endl;
}
void Person::Show() const { Data(); }
void Person::Set() {
std::cout << "Enter firstname: ";
std::cin >> firstname;
std::cout << "Enter lastname: ";
std::cin >> lastname;
}
pokerplayer.h:
#ifndef POKERPLAYER_H_
#define POKERPLAYER_H_
#include "person.h"
class PokerPlayer : virtual public Person {
public:
PokerPlayer(const char* fn = "none", const char* ln = "none")
: Person(fn, ln) {}
int Draw() const;
};
#endif // POKERPLAYER_H_
pokerplayer.cpp:
#include "pokerplayer.h"
#include
#include
int PokerPlayer::Draw() const {
srand(time(0));
return int(rand()) % 52 + 1;
}
gunslinger.h:
#ifndef GUNSLINGER_H_
#define GUNSLINGER_H_
#include "person.h"
class Gunslinger : virtual public Person {
private:
double drawtime;
int notches;
protected:
void Data() const;
public:
Gunslinger(const char* fn = "none", const char* ln = "none", double d = 0.0,
int n = 0)
: Person(fn, ln), drawtime(d), notches(n) {}
double Draw() const { return drawtime; }
double Notches() const { return notches; }
void Show() const;
void Set();
};
#endif // GUNSLINGER_H_
gunslinger.cpp:
#include "gunslinger.h"
#include
void Gunslinger::Data() const {
std::cout << "Draw: " << drawtime << std::endl;
std::cout << "Notches: " << notches << std::endl;
}
void Gunslinger::Show() const {
Person::Data();
Data();
}
void Gunslinger::Set() {
Person::Set();
std::cout << "Enter Drawtime: ";
std::cin >> drawtime;
std::cout << "Enter Notches: ";
std::cin >> notches;
}
baddude.h:
#ifndef BADDUDE_H_
#define BADDUDE_H_
#include "gunslinger.h"
#include "pokerplayer.h"
class BadDude : public PokerPlayer, public Gunslinger {
protected:
void Data() const;
public:
double Gdraw() const { return Gunslinger::Draw(); }
double Cdraw() const { return PokerPlayer::Draw(); }
void Show() const;
void Set();
};
#endif // BADDUDE_H_
baddude.cpp:
#include "baddude.h"
void BadDude::Data() const {
Gunslinger::Data();
PokerPlayer::Data();
}
void BadDude::Show() const { Data(); }
void BadDude::Set() { Gunslinger::Set(); }
main.cpp:
#include
#include
#include "baddude.h"
#include "gunslinger.h"
#include "person.h"
#include "pokerplayer.h"
const int SIZE = 5;
int main() {
using namespace std;
int ct, i;
Person* gang[SIZE];
for (ct = 0; ct < SIZE; ct++) {
char choice;
cout << "Enter the gang category: \n"
<< "o: ordinary person g: gunslinger "
<< "p: pokerplayer b: bad dude q: quit \n";
cin >> choice;
while (strchr("ogpbq", choice) == NULL) {
cout << "Please enter an o, g, p, b, or q: ";
cin >> choice;
}
if (choice == 'q') break;
switch (choice) {
case 'o':
gang[ct] = new Person;
break;
case 'g':
gang[ct] = new Gunslinger;
break;
case 'p':
gang[ct] = new PokerPlayer;
break;
case 'b':
gang[ct] = new BadDude;
break;
}
cin.get();
gang[ct]->Set();
}
cout << "\nHere is your gang: \n";
for (i = 0; i < ct; i++) {
cout << endl;
gang[i]->Show();
}
for (i = 0; i < ct; i++) delete gang[i];
cout << "Bye" << endl;
return 0;
}
5. 下面是一些类声明:
// emp.h -- header file for abstr_emp class and children #include
#include class abstr_emp { private: std::string fname; // abstr_emp's first name std::string lname; // abstr_emp's last name std::string job; public: abstr_emp(); abstr_emp(const std::string & fn, const std::string & ln, const std::string & j); virtual void ShowAll() const; // labels and shows all data virtual void SetAll(); // prompts user for values friend std::ostream & operator<<(std::ostream & os, 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(); };
注意,该类层次结构使用了带虚基类的MI,所以要牢记这种情况下用于构造函数初始化列表的特殊规则。还需要注意的是,有些方法被声明为保护的。这可以简化一些highfink
方法的代码(例如,如果highfink::ShowAll()
只是调用fink::ShowAll()
和manager::ShwAll()
,则它将调用abstr_emp::ShowAll()
两次)。请提供类方法的实现,并在一个程序中对这些类进行测试。下面是一个小型测试程序:
// 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; }
类方法的实现:emp.cpp:
#include "emp.h"
/********abstr_emp**********/
abstr_emp::abstr_emp() {
fname = "none";
lname = "none";
job = "none";
}
abstr_emp::abstr_emp(const std::string& fn, const std::string& ln,
const std::string& j)
: fname(fn), lname(ln), job(j) {}
abstr_emp::~abstr_emp() {}
void abstr_emp::ShowAll() const {
std::cout << "firstname: " << fname << std::endl;
std::cout << "lastname: " << lname << std::endl;
std::cout << "job: " << job << std::endl;
}
void abstr_emp::SetAll() {
std::cout << "Enter firstname: ";
std::getline(std::cin, fname);
std::cout << "Enter lastname: ";
std::getline(std::cin, lname);
std::cout << "Enter job: ";
std::getline(std::cin, job);
}
std::ostream& operator<<(std::ostream& os, const abstr_emp& e) {
os << e.lname << " " << e.fname << ", " << e.job;
return os;
}
/********employee**********/
employee::employee() {}
employee::employee(const std::string& fn, const std::string& ln,
const std::string& j)
: abstr_emp(fn, ln, j) {}
void employee::ShowAll() const { abstr_emp::ShowAll(); }
void employee::SetAll() { abstr_emp::SetAll(); }
/********manager**********/
manager::manager() { 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 = ico;
}
manager::manager(const manager& m) : abstr_emp(m) { inchargeof = m.inchargeof; }
void manager::ShowAll() const {
abstr_emp::ShowAll();
std::cout << "Inchargeof: " << inchargeof << std::endl;
}
void manager::SetAll() {
abstr_emp::SetAll();
std::cout << "Enter inchargeof: ";
std::cin >> inchargeof;
std::cin.get();
}
/********fink**********/
fink::fink() { reportsto = "none"; }
fink::fink(const std::string& fn, const std::string& ln, const std::string& j,
const std::string& rpo)
: abstr_emp(fn, ln, j), reportsto(rpo) {}
fink::fink(const abstr_emp& e, const std::string& rpo)
: abstr_emp(e), reportsto(rpo) {}
fink::fink(const fink& f) : abstr_emp(f) { reportsto = f.reportsto; }
void fink::ShowAll() const {
abstr_emp::ShowAll();
std::cout << "Reportsto: " << reportsto << std::endl;
}
void fink::SetAll() {
abstr_emp::SetAll();
std::cout << "Enter reportsto: ";
std::getline(std::cin, reportsto);
}
/********highfink**********/
highfink::highfink() {}
highfink::highfink(const std::string& fn, const std::string& ln,
const std::string& j, const std::string& rpo, int ico)
: abstr_emp(fn, ln, j), manager(fn, ln, j, ico), fink(fn, ln, j, rpo) {}
highfink::highfink(const abstr_emp& e, const std::string& rpo, int ico)
: abstr_emp(e), manager(e, ico), fink(e, rpo) {}
highfink::highfink(const fink& f, int ico)
: abstr_emp(f), fink(f), manager((const abstr_emp&)f, ico) {}
highfink::highfink(const manager& m, const std::string& rpo)
: abstr_emp(m), manager(m), fink((const abstr_emp&)m, rpo) {}
highfink::highfink(const highfink& h) : abstr_emp(h), manager(h), fink(h) {}
void highfink::ShowAll() const {
abstr_emp::ShowAll();
std::cout << "Inchargeof: " << manager::InChargeOf() << std::endl;
std::cout << "Reportsto: " << fink::ReportsTo() << std::endl;
}
void highfink::SetAll() {
abstr_emp::SetAll();
std::cout << "Enter reportsto: ";
std::getline(std::cin, fink::ReportsTo());
std::cout << "Enter Inchargeof: ";
std::cin >> manager::InChargeOf();
std::cin.get();
}
为什么没有定义赋值运算符?
类中不存在指针成员,不需要深拷贝,使用默认的赋值操作即可。
为什么要将ShowAll()
和SetAll()
定义为虚的?
因为派生类将修改基类中setAll()
与ShowAll()
两个函数的行为。
为什么要将abstr_emp
定义为虚基类?
虚基类使得highfink
从manager
和fink
继承过来,只包含一个abstr_emp
对象的拷贝,节省空间并避免不必要的冲突。
为什么highfink
类没有数据部分?
highfink
类需要的的数据成员已经包含在了它的父类中。
为什么只需要一个operator<<()
版本?
因为这里只显示基类中的三个成员,派生类基类中的基类部分将自动调用基类的友元函数。
如果使用下面的代码替换程序的结尾部分,将会发生什么情况?
abstr_emp tri[4] = {em, fi, hf, hf2}; for (int i = 0; i < 4; i++) tri[i].ShowAll();
编译失败,抽象类不能实例化。可以通过将virtua ~abstr_emp() = 0
改为virtual ~abstr_emp();
,即将abstr_emp
变成非抽象类,可编译通过,此时em
, fi
, hf
, hf2
这四个派生类对象将被强制转化为基类,所以只调用基类的ShowAll()
函数。