C++ Premier Plus 6th edition - Programming excercise - Chapter14 - 3

其实可以在类模板QueueTP中创建1个show(),通过循环连续返回queue中每个节点中存储的Worker*,但怎么将这个指针与相应的类成员函数(如Singer的show() )联系起来用,我还没有想到好办法。
想到在QueueTP用函数指针,比如show(*pf),然后pf可以使用相应派生类的成员函数show(),但没有实现。后面再回过头来想想吧。
最终只能仍然是用Worker指针数组去完成的显示。
queuetp.h

#ifndef QUEUETP_H_
#define QUEUETP_H_
#include<iostream>
#include<string>

// Part 1: class QueueTP
template <typename T>
class QueueTP
{
private:
    // class scope definitions
    // Node is a nested structure definition local to this class
    struct Node
    {
        T item;
        struct Node * next;
    };
    enum { Q_SIZE = 10 };
    // private class members
    Node * front; // pointer to front of Queue
    Node * rear; // pointer to rear of Queue
    int items; // current number of items in Queue
    const int qsize; // maximum number of items in Queue
    // preemptive definitions to prevent public copying
    QueueTP(const QueueTP & q) : qsize(0) {};
    QueueTP & operator=(const QueueTP & q)
    {
        return *this;
    }
public:
    QueueTP(int qs = Q_SIZE); // create queue with a qs limit
    ~QueueTP();
    bool isempty() const;
    bool isfull() const;
    int queuecount() const;
    bool enqueue(const T &item); // add item to end
    bool dequeue(T &item); // remove item from front
};

// Queue methods
template<typename T>
QueueTP<T>::QueueTP(int qs) : qsize(qs)
{
    front = rear = NULL; // or nullptr
    items = 0;
}
template<typename T>
QueueTP<T>::~QueueTP()
{
    Node * temp;
    while (front != NULL) // while queue is not yet empty
    {
        temp = front; // save address of front item
        front = front->next;// reset pointer to next item
        delete temp; // delete former front
    }
}
template<typename T>
bool QueueTP<T>::isempty() const
{
    return items == 0;
}
template<typename T>
bool QueueTP<T>::isfull() const
{
    return items == qsize;
}
template<typename T>
int QueueTP<T>::queuecount() const
{
    return items;
}
// Add item to queue
template<typename T>
bool QueueTP<T>::enqueue(const T & item)
{
    if (isfull())
        return false;
    Node * add = new Node; // create node
    // on failure, new throws std::bad_alloc exception
    add->item = item; // set node pointers
    add->next = NULL; // or nullptr;
    items++;
    if (front == NULL) // if queue is empty,
        front = add; // place item at front
    else
        rear->next = add; // else place at rear
    rear = add; // have rear point to new node
    return true;
}
// Place front item into item variable and remove from queue
template<typename T>
bool QueueTP<T>::dequeue(T & item)
{
    if (front == NULL)
        return false;
    item = front->item; // set item to first item in queue
    items--;
    Node * temp = front; // save location of first item
    front = front->next; // reset front to next item
    delete temp; // delete former first item
	/*
	because the pointer "first" was moved to point other item,
	without temp,will lose track of the first item,it will be left in heap
	forever.
	*/
	// items counts how many items in queue,if no items left, rear points to null
    if (items == 0)
        rear = NULL;
    return true;
}

// Part 2: class Worker,Waiter,Singerwaiter
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 const 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

queuetp.cpp

// implementations
#include "queuetp.h"
#include <iostream>
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
const char * Singer::pv[Singer::Vtypes] = { "other", "alto", "contralto",
                                            "soprano", "bass", "baritone", "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';
    cin >> voice;
    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();
}

main.cpp

// implementations
// class functions templates must be placed in same file with class declaration
#include <iostream>
#include <cstring>
#include "queuetp.h"
const int SIZE = 10;
int main()
{
    using std::cin;
    using std::cout;
    using std::endl;
    using std::strchr;

    // use default constructor creating a QueueTP of 10 elements
    // each element is a pointer of Worker
    // original solution use array storing Worker*
    // this solution use queue storing Worker*
    // used to store Cutomer obj using queue
    // here we use queue to store Worker*
    QueueTP<Worker*> qworker;
    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;
            qworker.enqueue(lolas[ct]);
            break;
        case 's':
            lolas[ct] = new Singer;
            qworker.enqueue(lolas[ct]);
            break;
        case 't':
            lolas[ct] = new SingingWaiter;
            qworker.enqueue(lolas[ct]);
            break;
        }
        cin.get();
        lolas[ct]->Set();
    }
    cout << "\nHere is your staff:\n";
	for (int i = 0; i < ct; i++)
		lolas[i]->Show();


    cout << "\nThere are totally " << qworker.queuecount() << " items in queue. \n";
    for (int i = 0; i < ct; i++)
        delete lolas[i];// as in switch used new
    cout << "Bye.\n";
    cin.get();
    cin.get();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值