2021-04-19 C++ Primer Plus 第十四章 C++中的代碼重用 編程練習(xí)

編程練習(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'”!。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容