編程練習(xí)
1.Wine 類有一個(gè)string 類對象成員和一個(gè)Pair對象;其中前者用于存儲葡萄酒的名稱,而后者有兩個(gè)valarry<int>對象,這兩個(gè)valarray<int>對象分別保存了葡萄酒的釀造年份和該年生產(chǎn)的瓶數(shù)。
Winec.h
//
// Created by a1358 on 2021/4/9.
//
#ifndef WINE_WINEC_H
#define WINE_WINEC_H
#include <string>
#include <valarray>
using namespace std;
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() {}
};
typedef std::valarray<int> ArrayInt;
typedef Pair<ArrayInt,ArrayInt> PairArray;
class Wine {
private:
string wine_name;
PairArray year_count;
int years;
public:
Wine();
~Wine();
Wine(const char * l, int y, const int yr[], const int bot[]);
Wine(const char * l, int y);
void GetBottle();
void Show();
string & Label();
int sum();
};
#endif //WINE_WINEC_H
Winec.cpp
//
// Created by a1358 on 2021/4/9.
//
#include "Winec.h"
#include <iostream>
template<class T1, class T2>
T1 & Pair<T1,T2>::first()
{
return a;
}
template<class T1, class T2>
T2 & Pair<T1,T2>::second()
{
return b;
}
Wine::Wine() {
wine_name = "MOUTAI";
year_count=PairArray(ArrayInt(0),ArrayInt(0));
years = 0;
}
Wine::~Wine() {
}
Wine::Wine(const char *l, int y, const int *yr, const int *bot) {
wine_name = l;
years = y;
year_count=PairArray(ArrayInt(yr,y),ArrayInt(bot,y));
\
}
Wine::Wine(const char *l, int y) {
wine_name = l;
years = y;
year_count=PairArray(ArrayInt(0),ArrayInt(0));
}
void Wine::GetBottle() {
cout << "Enter " << wine_name << " data for "
<< years << " year(s):" << endl;
for(int i = 0; i < years; i++)
{
cout << "Enter year: ";
cin >> year_count.first()[i];
cout << "Enter bottles for that year: ";
cin >> year_count.second()[i];
}
}
void Wine::Show() {
cout << "Wine: " << wine_name << endl;
cout << "\tYear" <<"\tBottles" << endl;
for(int i = 0; i < years; i++)
{
cout << "\t" << year_count.first()[i]
<< "\t" << year_count.second()[i] << endl;
}
}
string & Wine::Label() {
return wine_name;
}
int Wine::sum() {
return year_count.second().sum();
}
main.cpp
#include <iostream>
#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);
holding.GetBottle();
holding.Show();
const int YRS =3 ;
int y[YRS] = {1993, 1995, 1998};
int b[YRS] = { 48, 60 ,72};
Wine more("Gushing Grape Red",YRS,y ,b);
more.Show();
cout << "Total bottles for " << more.Label()
<< ": "<< more.sum() << endl;
cout << "Bye\n";
return 0;
}
2.采用私有繼承而不是包含來完成編程練習(xí)1。同樣,一些typedef可能會有所幫助,另外,您可能還需要考慮諸如下面這樣的語句的含義;
PairArray::operator=(PairArray(ArrayInt(),ArrayInt()));
cout << (const string &)(*this);
您設(shè)計(jì)的類應(yīng)該可以使用編程練習(xí)1中的測試程序進(jìn)行測試。
Winec.h
//
// Created by a1358 on 2021/4/9.
//
#ifndef WINE_WINEC_H
#define WINE_WINEC_H
#include <string>
#include <valarray>
using namespace std;
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() {}
};
typedef std::valarray<int> ArrayInt;
typedef Pair<ArrayInt,ArrayInt> PairArray;
class Wine : private PairArray,
private string {
private:
int years;
public:
Wine()
:string(nullptr),years(0),PairArray(ArrayInt(0),ArrayInt(0)){}
~Wine(){}
Wine(const char * l, int y, const int yr[], const int bot[])
:string(l),years(y),PairArray(ArrayInt(yr,y),ArrayInt(bot,y)){}
Wine(const char * l, int y)
:string(l),years(y),PairArray(ArrayInt(y),ArrayInt(y)){}
void GetBottle();
void Show();
string & Label();
int sum();
};
#endif //WINE_WINEC_H
Winec.cpp
//
// Created by a1358 on 2021/4/9.
//
#include "Winec.h"
#include <iostream>
template<class T1, class T2>
T1 & Pair<T1,T2>::first()
{
return a;
}
template<class T1, class T2>
T2 & Pair<T1,T2>::second()
{
return b;
}
void Wine::GetBottle() {
cout << "Enter " << *this << " data for "
<< years << " year(s):" << endl;
for(int i = 0; i < years; i++)
{
cout << "Enter year: ";
cin >> this->first()[i];
cout << "Enter bottles for that year: ";
cin >> this->second()[i];
}
}
void Wine::Show() {
cout << "Wine: " << *this << endl;
cout << "\tYear" <<"\tBottles" << endl;
for(int i = 0; i < years; i++)
{
cout << "\t" << this->first()[i]
<< "\t" << this->second()[i] << endl;
}
}
string & Wine::Label() {
return *this;
}
int Wine::sum() {
return this->second().sum();
}
main.cpp
#include <iostream>
#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);
holding.GetBottle();
holding.Show();
const int YRS =3 ;
int y[YRS] = {1993, 1995, 1998};
int b[YRS] = { 48, 60 ,72};
Wine more("Gushing Grape Red",YRS,y ,b);
more.Show();
cout << "Total bottles for " << more.Label()
<< ": "<< more.sum() << endl;
cout << "Bye\n";
return 0;
}
3.定義一個(gè)QueneTp模板。然后在一個(gè)類似于程序清單14.12的程序中創(chuàng)建一個(gè)指向Worker的指針隊(duì)列,并使用該隊(duì)列來測試它。
QueueTp.h
#include <string>
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() {}
virtual void Set();
virtual void Show() const;
};
template<class T>
class QueueTp
{
private:
enum {Q_SIZE = 10};
struct Node
{
T item;
Node * next;
};
// class members
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 enqueue(const T & item);
bool dequeue(T & item);
};
template <typename T>
QueueTp<T>::QueueTp(int qs) : qsize(qs)
{
front = rear = NULL;
items = 0;
}
template <typename T>
QueueTp<T>::~QueueTp()
{
Node * temp;
while (front != NULL)
{
temp = front;
front = front->next;
delete temp;
}
}
template <typename T>
bool QueueTp<T>::enqueue(const T & item)
{
if(isfull())
return false;
Node * add = new Node;
if (front == NULL) // if queue is empty
{
add->item = item;
add->next = NULL;
front = rear = add;
}
else
{
add->item = item;
add->next = NULL;
rear->next = add;
rear = add;
}
items++;
return true;
}
template <typename T>
bool QueueTp<T>::dequeue(T & item)
{
if(isempty())
return false;
item = front->item;
Node * temp;
temp = front;
front = front->next;
delete temp;
items--;
return true;
}
QueueTp.cpp
//
// Created by a1358 on 2021/4/12.
//
#include "QueneTp.h"
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
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";
}
main.cpp
#include <iostream>
#include <cstring>
#include "QueneTp.h"
const int SIZE = 10;
int main() {
using std::cin;
using std::cout;
using std::endl;
using std::strchr;
QueueTp<Worker>q(3);
if(q.isempty())
cout << "Queue is empty" << endl;
cout << "add worker1 to queue..." << endl;
Worker w1("shao", 1);
q.enqueue(w1);
Worker w;
cout << "delete worker1..." << endl;
q.dequeue(w);
w.Show();
return 0;
}
4.Person類保存人的名和姓。除構(gòu)造函數(shù)外,它還有Show()方法,用于顯示名和姓。Gunslinger類以Person類為虛基類派生而來,它包含一個(gè)Draw()成員,該方法返回一個(gè)double值,表示槍手的拔槍時(shí)間...
Person.h
//
// Created by a1358 on 2021/4/12.
//
#ifndef PERSON_PERSON_H
#define PERSON_PERSON_H
#include <string>
using std::string;
class Person {
private:
string firstname;
string lastname;
public:
Person():firstname("null"),lastname("null"){}
Person(const string &f,const string &l):firstname(f),lastname(l){}
virtual void Set();
virtual ~Person() = 0;
virtual void Show() ;
};
class Gunslinger :virtual public Person
{
private:
int count;
public:
Gunslinger():Person(),count(0){}
Gunslinger(const string &f,const string &l,int c):Person(f,l),count(c){}
virtual void Set();
int Draw();
virtual void Show();
};
struct card{
string color;
int value;
};
class PokePlayer :virtual public Person
{
private:
public:
card Draw();
virtual void Set();
virtual void Show();
};
class BadDude : public Gunslinger, public PokePlayer{
public:
BadDude(){};
BadDude(const string & f,const string & l,int c):Person(f,l),Gunslinger(f,l,c){}
virtual void Set();
int Gdraw();
card Cdraw();
virtual void Show();
};
#endif //PERSON_PERSON_H
Person.cpp
//
// Created by a1358 on 2021/4/12.
//
#include <stdlib.h>
#include "Person.h"
#include <iostream>
using std::cout;
using std::endl;
using std::cin;
Person::~Person() {
}
void Person::Set() {
cout <<"Enter firstname: ";
cin >> firstname;
cout << endl;
cout << "Enter lastname: ";
cin >> lastname;
cout << endl;
}
void Person::Show() {
cout << "firstname: " << firstname << endl
<< "lastname: " << lastname << endl;
}
int Gunslinger::Draw() {
void srand (unsigned int seed);
int a = rand() % 10;
return a;
}
void Gunslinger::Set() {
Person::Set();
cout << "Enter counts: ";
cin >> count;
cout << endl;
}
void Gunslinger::Show() {
Person::Show();
cout << "spear time: " << Draw() << endl
<< "nicks: " << count << endl;
}
card PokePlayer::Draw() {
card poke;
poke.color = "Club";
poke.value = 10;
return poke;
}
void PokePlayer::Set() {
Person::Set();
}
void PokePlayer::Show() {
Person::Show();
cout << "card color: " << Draw().color << endl
<< "card value: " << Draw().value << endl;
}
int BadDude::Gdraw() {
void srand (unsigned int seed);
int a = rand() % 10;
return a;
}
card BadDude::Cdraw() {
card c;
c.value = 6;
c.color = "Heart";
return c;
}
void BadDude::Set() {
Person::Set();
}
void BadDude::Show() {
Person::Show();
cout << "spear time: " << Gdraw() << endl;
cout << "card color: " << Cdraw().color << endl
<< "card value: " << Cdraw().value << endl;
}
main.cpp
#include <iostream>
#include <cstring>
#include "Person.h"
const int SIZE = 3;
int main()
{
using std::cin;
using std::cout;
using std::endl;
using std::strchr;
Person * lolas[SIZE];
int ct;
for (ct = 0; ct < SIZE; ct++)
{
char choice;
cout << "Enter the employee category:\n"
<< "g: Gunslinger p: PokePlayer "
<< "b: BadDude q: quit\n";
cin >> choice;
while (strchr("gpbq", choice) == NULL)
{
cout << "Please enter a g, p, b, or q: ";
cin >> choice;
}
if (choice == 'q')
break;
switch(choice)
{
case 'g': lolas[ct] = new Gunslinger;
break;
case 'p': lolas[ct] = new PokePlayer;
break;
case 'b': lolas[ct] = new BadDude;
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";
return 0;
}
5.下面是一些類聲明
#include <iostream>
#include <string>
class abstr_emp {
private:
std::string fname;
std::string lname;
std::string job;
public:
abstr_emp();
abstr_emp(const std::string & fn, const std::string & ln,
const std::string & j);
virtual void ShowAll() const;
virtual void SetAll();
friend std::ostream &
operator<<(std::ostream & os, const abstr_emp & e);
virtual ~abstr_emp() = 0;
};
class employee: public abstr_emp
{
public:
employee();
employee(const std::string & fn, const std::string & ln,
const std::string & j);
virtual void ShowAll() const;
virtual void SetAll();
};
class mananger : virtual public abstr_emp
{
private:
int inchargeof;
protected:
int InchargeOf() const { return inchargeof;}
int & InchargeOf() { return inchargeof; }
public:
mananger();
mananger(const std::string & fn, const std::string & ln,
const std::string & j, int ico = 0);
mananger(const abstr_emp & e,int ico);
mananger(const mananger &m);
virtual void ShowAll() const;
virtual void SetAll();
};
class fink : virtual public abstr_emp
{
private:
std::string reportersto;
protected:
const std::string ReportsTo() const {return reportersto;}
std::string & ReportsTo() {return reportersto;}
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 mananger, public fink
{
public:
highfink();
highfink(const std::string & fn, const std::string &ln,
const std::string & j, const std::string & rpo,
int ico);
highfink(const abstr_emp & e,const std::string & rpo,int ico);
highfink(const fink & f,int ico);
highfink(const mananger &m, const std::string & rpo);
highfink(const highfink & h);
virtual void ShowAll() const;
virtual void SetAll();
};
請?zhí)峁╊惙椒ǖ膶?shí)現(xiàn),并在一個(gè)程序中對這些類進(jìn)行測試。下面是一個(gè)小型測試程序:
#include <iostream>
using namespace std;
#include "emp.h"
int main(void) {
employee em("Trip","Harris","Thumper");
cout << em << endl;
em.ShowAll();
mananger 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");
hf.ShowAll();
cout << "Press a key for next phare:\n";
cin.get();
highfink hf2;
hf2.ShowAll();
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;
}
為什么沒有定義賦值運(yùn)算符?
string類中包含了賦值運(yùn)算符
為什么要將ShowAll()和SetAll()定義為虛?
因?yàn)榘鸦惖某蓡T函數(shù)定義為虛后,程序?qū)⒏鶕?jù)引用或指針指向的對象的類型來選擇方法,所以當(dāng)定義基類指針或引用后,在派生類中可以調(diào)用相對應(yīng)的虛成員函數(shù)。
為什么要將abstr_emp定義為虛基類?
虛基類使得從多個(gè)類(它們的基類相同)派生出的對象只繼承一個(gè)基類對象。派生類hignfink只會繼承一個(gè)abstr_emp對象。
為什么highfink類沒有數(shù)據(jù)部分?
highfink類繼承了mananger和fink的保護(hù)域和公有域的作為數(shù)據(jù)部分。
為什么只需要一個(gè)operator<<()版本?
因?yàn)閙ananger和fink類繼承了abstr_emp的operator<<函數(shù)
如果使用下面的代碼替換程序的結(jié)尾,將會發(fā)生什么情況?
abstr_emp tri[4] = {em,fi,hf,hf2};
for(int i = 0; i < 4; i++)
{
tri[i].ShowAll();
}
em,fi,hf,hf2這四個(gè)派生類對象將被強(qiáng)制轉(zhuǎn)化為基類,而abstr_emp為虛基類,無法創(chuàng)建對象,所以程序會報(bào)錯(cuò),
“invalid abstract type 'abstr_emp' for 'tri'”!。