编程练习
1.Wine 类有一个string 类对象成员和一个Pair对象;其中前者用于存储葡萄酒的名称,而后者有两个valarry<int>对象,这两个valarray<int>对象分别保存了葡萄酒的酿造年份和该年生产的瓶数。
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.采用私有继承而不是包含来完成编程练习1。同样,一些typedef可能会有所帮助,另外,您可能还需要考虑诸如下面这样的语句的含义;
PairArray::operator=(PairArray(ArrayInt(),ArrayInt()));
cout << (const string &)(*this);
您设计的类应该可以使用编程练习1中的测试程序进行测试。
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.定义一个QueneTp模板。然后在一个类似于程序清单14.12的程序中创建一个指向Worker的指针队列,并使用该队列来测试它。
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类保存人的名和姓。除构造函数外,它还有Show()方法,用于显示名和姓。Gunslinger类以Person类为虚基类派生而来,它包含一个Draw()成员,该方法返回一个double值,表示枪手的拔枪时间...
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();
};
请提供类方法的实现,并在一个程序中对这些类进行测试。下面是一个小型测试程序:
#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;
}
为什么没有定义赋值运算符?
string类中包含了赋值运算符
为什么要将ShowAll()和SetAll()定义为虚?
因为把基类的成员函数定义为虚后,程序将根据引用或指针指向的对象的类型来选择方法,所以当定义基类指针或引用后,在派生类中可以调用相对应的虚成员函数。
为什么要将abstr_emp定义为虚基类?
虚基类使得从多个类(它们的基类相同)派生出的对象只继承一个基类对象。派生类hignfink只会继承一个abstr_emp对象。
为什么highfink类没有数据部分?
highfink类继承了mananger和fink的保护域和公有域的作为数据部分。
为什么只需要一个operator<<()版本?
因为mananger和fink类继承了abstr_emp的operator<<函数
如果使用下面的代码替换程序的结尾,将会发生什么情况?
abstr_emp tri[4] = {em,fi,hf,hf2};
for(int i = 0; i < 4; i++)
{
tri[i].ShowAll();
}
em,fi,hf,hf2这四个派生类对象将被强制转化为基类,而abstr_emp为虚基类,无法创建对象,所以程序会报错,
“invalid abstract type 'abstr_emp' for 'tri'”!。