其实可以在类模板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;
}