书籍:C++ Primer Plus (第六版)(中文版)
工具:Dev-C++ 5.11
电脑信息:Intel® Xeon® CPU E5-2603 v3 @ 1.60GHz
系统类型:64位操作系统,基于X64的处理器 windows10 专业版
第14章 C++中的代码重用
14.3 多重继承
实例14.4
之前编译失败,是因为没有析构函数。
workermi.h
workermi.cpp
cpp
//Worker methods
Worker::~Worker()
{
}
workmi.cpp
编译运行结果:
cpp
Enter the employee category:
w: waiter s: singer t:singing waiter q:quit
w
Enter waiter's name: wally fff
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: sinpad pa
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: naldafsfg f
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
Please enter a, w, s, t, or q: d
Please enter a, w, s, t, or q: q
Please enter a, w, s, t, or q: q
Please enter a, w, s, t, or q: q
Please enter a, w, s, t, or q: q
Please enter a, w, s, t, or q: Q
Please enter a, w, s, t, or q:
退不出来。
是因为
while (strchr("wstp", choice) == NULL)
写错了,应该时q,输入的时候习惯输入q,导致退不出来。
修改后再编译运行:
cpp
Enter the employee category:
w: waiter s: singer t:singing waiter q:quit
w
Enter waiter's name: sfsgsg
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: dghdhj
Enter worker's ID: 1020
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
t
Enter singing waiter's name: ghfgj
Enter worker's ID: 1256
Enter waiter's panache rating: 3
Enter number for singer's vocal range:
0: other 1: alto 2: contralto 3: soprano
4: bass 5: baritone 6: tenor
6
Enter the employee category:
w: waiter s: singer t:singing waiter q:quit
q
Here is your staff:
Category: waiter
Name: sfsgsg
Employee ID: 1040
Panache rating: 4
Category: singer
Name: dghdhj
Employee ID: 1020
Vocal range:soprano
Category: singing waiter
Name: ghfgj
Employee ID: 1256
Vocal range:tenor
Panache rating: 3
Bye.
请按任意键继续. . .
14.4 类模板
实例14.5
stacktp.h
cpp
// stacktp.h -- a stack template
#ifndef STACKTP_H_
#define STACKTP_H_
template <class Type>
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 <class Type>
Stack<Type>::Stack()
{
top = 0;
}
template <class Type>
bool Stack<Type>::isempty()
{
return top == 0;
}
template <class Type>
bool Stack<Type>::isfull()
{
return top == MAX;
}
template <class Type>
bool Stack<Type>::push(const Type & item)
{
if (top < MAX)
{
items[top++] = item;
return true;
}
else
return false;
}
template <class Type>
bool Stack<Type>::pop(Type & item)
{
if (top > 0)
{
item = items[--top];
return true;
}
else
return false;
}
#endif // STACKTP_H_
stacktem.cpp
cpp
// stacktem.cpp -- testing the template stack class
#include <iostream>
#include <string>
#include <cctype>
#include "stacktp.h"
using std::cin;
using std::cout;
int main()
{
Stack<std::string> 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";
return 0;
}
编译运行结果:
cpp
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
--------------------------------
Process exited after 119.6 seconds with return value 0
请按任意键继续. . .
实例14.6
stcktp1.h
cpp
// stcktp1.h -- modified Stack template
#ifndef STCKTP1_H_
#define STCKTP1_H_
template <class Type>
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 <class Type>
Stack<Type>::Stack(int ss) : stacksize(ss), top(0)
{
items = new Type [stacksize];
}
template <class Type>
Stack<Type>::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 <class Type>
bool Stack<Type>::push(const Type & item)
{
if (top < stacksize)
{
items[top++] = item;
return true;
}
else
return false;
}
template <class Type>
bool Stack<Type>::pop(Type & item)
{
if (top > 0)
{
item = items[--top];
return true;
}
else
return false;
}
template <class Type>
Stack<Type> & Stack<Type>::operator=(const Stack<Type> & 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
cpp
// stkoptr1.cpp -- testing stack of pointers
#include <iostream>
#include <cstdlib> // for rand(), srand()
#include <ctime> // 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<const char *> 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;
}
编译运行结果:
cpp
Please enter stack size: 5
1: Hank Gilgamesh
2: Kiki Ishtar
4: Ian Flagranti
5: Wolfgang Kibble
3: Betty Rocker
8: Xaverie Paprika
7: Joy Almondo
9: Juan Moore
6: Portia Koop
10: Misha Mache
Bye
--------------------------------
Process exited after 9.639 seconds with return value 0
请按任意键继续. . .
实例14.7
arraytp.h
cpp
//arraytp.h -- Array Template
#ifndef ARRAYTP_H
#define ARRAYTP_H
#include <iostream>
#include <cstdlib>
template <class T, int n> // T为类型参数,n为int类型(非类型/表达式参数)
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 <class T, int n>
ArrayTP<T,n>::ArrayTP(const T & v)
{
for (int i = 0; i < n; i++)
ar[i] = v;
}
template <class T, int n>
T & ArrayTP<T,n>::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 <class T, int n>
T ArrayTP<T,n>::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
cpp
// twod.cpp -- making a 2-d array
#include <iostream>
#include "arraytp.h"
int main(void)
{
using std::cout;
using std::endl;
ArrayTP<int, 10> sums;
ArrayTP<double, 10> aves;
ArrayTP< ArrayTP<int,5>, 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] / 10;
}
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";
return 0;
}
编译运行结果:
cpp
1 2 3 4 5 : sum = 15, average = 1.5
2 4 6 8 10 : sum = 30, average = 3
3 6 9 12 15 : sum = 45, average = 4.5
4 8 12 16 20 : sum = 60, average = 6
5 10 15 20 25 : sum = 75, average = 7.5
6 12 18 24 30 : sum = 90, average = 9
7 14 21 28 35 : sum = 105, average = 10.5
8 16 24 32 40 : sum = 120, average = 12
9 18 27 36 45 : sum = 135, average = 13.5
10 20 30 40 50 : sum = 150, average = 15
Done.
--------------------------------
Process exited after 0.3708 seconds with return value 0
请按任意键继续. . .
实例14.8
pairs.cpp
cpp
// pairs.cpp -- defining and using a Pair template
#include<iostream>
#include<string>
template<class T1, class T2>
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<class T1, class T2>
T1 & Pair<T1, T2>::first(){
return a;
}
template<class T1, class T2>
T2 & Pair<T1, T2>::second(){
return b;
}
int main(){
using std::cout;
using std::endl;
using std::string;
Pair<string, int> ratings[4] = {
Pair<string, int>("The Purpled Duck", 5),
Pair<string, int>("Jaquie's Frisco Al Rresco", 4),
Pair<string, int>("Cafe Souffle", 5),
Pair<string, int>("Bertie's Eats", 3)
};
int joints = sizeof(ratings) / sizeof(Pair<string, int>);
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;
return 0;
}
编译运行结果:
cpp
Rating: Eatery
5: The Purpled Duck
4: Jaquie's Frisco Al Rresco
5: Cafe Souffle
3: Bertie's Eats
Oops! Revised rating:
6: Bertie's Fab Eats
--------------------------------
Process exited after 0.3374 seconds with return value 0
请按任意键继续. . .
实例14.9
tempmemb.cpp
cpp
// tempmemb.cpp -- template members
#include<iostream>
using std::cout;
using std::endl;
template<typename T>
class beta{
private:
template <typename V> // 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<T> q; // template object
hold<int> n; // template object
public:
beta( T t, int i) : q(t), n(i) {}
template<typename U> // 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<double> 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";
return 0;
}
编译运行结果:
cpp
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
--------------------------------
Process exited after 0.321 seconds with return value 0
请按任意键继续. . .
实例14.10
tempparm.cpp
cpp
// tempparm.cpp - template as parameters
#include <iostream>
#include"stacktp.h"
template < template <typename T> class Thing>
class Crab{
private:
Thing<int> s1;
Thing<double> s2;
public:
Crab() { };
// assume the thing class 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<Stack> nebula; // Stack must match template <typename T> 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";
return 0;
}
加载之前的stacktp.h文件
编译运行结果:
```cpp
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.
--------------------------------
Process exited after 23.26 seconds with return value 0
请按任意键继续. . .
实例14.11
frnd2tmp.cpp
cpp
// frnd2tmp.cpp -- template class with non-template friends
#include <ctime>
#include<iostream>
using std::cout;
using std::endl;
template<typename T>
class HasFriend{
private:
T item;
static int ct;
public:
HasFriend(const T & i) : item(i) { ct++; }
~HasFriend() { ct--; }
friend void counts();
friend void report(HasFriend<T> &); // template parameter
};
// each specialization has its own static data member
template<typename T>
int HasFriend<T>::ct = 0;
// non-template friend to all HasFriend<T> classes
void counts(){
cout << "int count: " << HasFriend<int>::ct << "; ";
cout << "double count: " << HasFriend<double>::ct << endl;
}
// non-template friend to the HasFriend<int> class
void report(HasFriend<int> & hf){
cout << "HasFriend<int>: " << hf.item << endl;
}
// non-template friend to the HasFriend<double class
void report(HasFriend<double> & hf){
cout << "HasFriend<double>: " << hf.item << endl;
}
int main(){
cout << "No objects declared: ";
counts();
HasFriend<int>hfil(10);
cout <<"After hfil declared: ";
counts();
HasFriend<int>hfil2(20);
cout << "After hfil2 declared: ";
counts();
HasFriend<double>hfdb(10.5);
cout << "After hfdb declared: ";
counts();
report(hfil);
report(hfil2);
report(hfdb);
return 0;
}
编译运行结果:
```cpp
No objects declared: int count: 0; double count: 0
After hfil declared: int count: 1; double count: 0
After hfil2 declared: int count: 2; double count: 0
After hfdb declared: int count: 2; double count: 1
HasFriend<int>: 10
HasFriend<int>: 20
HasFriend<double>: 10.5
--------------------------------
Process exited after 0.3272 seconds with return value 0
请按任意键继续. . .
实例14.12
tmp2tmp.cpp
cpp
// tmp2tmp.cpp -- template friends to a template class
#include<iostream>
using std::cout;
using std::endl;
// template prototypes
template<typename T> void counts();
template<typename T> void report(T &);
// template class
template <typename TT>
class HasFriendT{
private:
TT item;
static int ct;
public:
HasFriendT(const TT & i) : item(i) { ct++; }
~HasFriendT() { ct--;}
friend void counts<TT>();
friend void report<>(HasFriendT<TT> &);
};
template<typename T>
int HasFriendT<T>::ct = 0;
// template friend functions definitions
template<typename T>
void counts(){
cout << "template size: " << sizeof(HasFriendT<T>) << ": ";
cout << "template counts(): " << HasFriendT<T>::ct << endl;
}
template<typename T>
void report(T & hf){
cout << hf.item << endl;
}
int main(){
counts<int>();
HasFriendT<int> hfil(10);
HasFriendT<int> hfil2(20);
HasFriendT<double> hfdb(10.5);
report(hfil); // generate report(HasFriendT<int> &)
report(hfil2); // generate report(HasFriendT<int> &)
report(hfdb); // generate report(HasFriendT<double> &)
cout << "counts<int>() output: \n";
counts<int>();
cout << "counts<double>() output: \n";
counts<double>();
return 0;
}
编译运行结果:
cpp
template size: 4: template counts(): 0
10
20
10.5
counts<int>() output:
template size: 4: template counts(): 2
counts<double>() output:
template size: 8: template counts(): 1
--------------------------------
Process exited after 0.3314 seconds with return value 0
请按任意键继续. . .
实例14.13
manyfrnd.cpp
cpp
// manyfrnd.cpp -- unbound template friend to a template class
#include<iostream>
using std::cout;
using std::endl;
template<typename T>
class ManyFriend{
private:
T item;
public:
ManyFriend(const T & i) : item(i) { }
template <typename C, typename D> friend void show2(C &, D &);
};
template <typename C, typename D> void show2(C & c, D & d){
cout << c.item << ", " << d.item << endl;
}
int main(){
ManyFriend<int> hfil(10);
ManyFriend<int> hfil2(20);
ManyFriend<double> hfdb(10.5);
cout << "hfil, hfil2: ";
show2(hfil, hfil2);
cout << "hfdb, hfil2: ";
show2(hfdb, hfil2);
return 0;
}
编译运行结果:
cpp
hfil, hfil2: 10, 20
hfdb, hfil2: 10.5, 20
--------------------------------
Process exited after 0.3257 seconds with return value 0
请按任意键继续. . .