Reusing Code in C++

Classes with Object Members



// studentc.h -- defining a Student class using containment

#ifndef _STUDNTC_H_
#define _STUDENTC_H_

#include <iostream.h>
#include "aritharr.h"  // from Chapter 12
#include "strng2.h"    // from Chapter 11

class Student
{
private:
	String name;
	ArithArr scores;
public:
	Student() : name("Null Student"), scores() {}
	Student(const String & s)
		: name(s), scores() {}
	Student(int n) : name("Nully"), scores(n) {}
	Student(const String & s, int n)
		: name(s), scores(n) {}
	Student(const String & s, const ArithArr & a)
		: name(s), scores(a) {}
	Student(const char * str, const double * pd, int n)
		: name(str), scores(pd, n) {}
	~Student() {}
	double & operator[](int i);
	const double & operator[](int i) const;
	double average() const;

// friends
	friend ostream & operator<<(ostream & os, const Student & stu);
	friend istream & operator>>(istream & os, Student & su);
};

#endif



// studentc.cpp -- student class

#include "studentc.h"
double Student::average() const
{
	return scores.average();
}

double & Student::operator[](int i)
{
	return scores[i];
}

const double & Student::operator[](int i) const
{
	return scores[i];
}

// friends
ostream & operator<<(ostream & os, const Student & stu)
{
	os << "Scores for " << stu.name << ":\n";
	os << stu.scores;
	return os;
}

istream & operator>>(istream & is, Student & stu)
{
	is >> stu.name;
	return is;
}



Private Inheritance



// studenti.h -- defining a Student class using private inheritance

#ifndef _STUDNTI_H_
#define _STUDENTI_H_

#include <iostream.h>
#include "aritharr.h"
#include "strng2.h"

class Student : private String, private ArithArr
{
public:
	Student() : String("Null Student"), ArithArr() {}
	Student(const String & s)
		: String(s), ArithArr() {}
	Student(int n) : String("Nully"), ArithArr(n) {}
	Student(const String & s, int n)
		: String(s), ArithArr(n) {}
	Student(const String & s, const ArithArr & a)
		: String(s), ArithArr(a) {}
	Student(const char * str, const double * pd, int n)
		: String(str), ArithArr(pd, n) {}
	~Student() {}
	double & operator[](int i);
	const double & operator[](int i) const;
	double average() const;
// friends
	friend ostream & operator<<(ostream & os, const Student & stu);
	friend istream & operator>>(istream & os, Student & su);
};

#endif



// studenti.cpp -- a student class using private inheritance

#include "studenti.h"
double Student::average() const
{
	return ArithArr::average();
}

double & Student::operator[](int i)
{
	return  ArithArr::operator[](i);
}

const double & Student::operator[](int i) const
{
	return ArithArr::operator[](i);
}

// friends
ostream & operator<<(ostream & os, const Student & stu)
{
	os << "Scores for " << (const String &) stu << ":\n";
	os << (const ArithArr &) stu;
	return os;
}

istream & operator>>(istream & is, Student & stu)
{
	is >> (String &) stu;
	return is;
}



// use_stui.cpp -- use a class with private derivation

// compile with studenti.cpp, strng2.cpp, arraydb.cpp, and aritharr.cpp
#include <iostream.h>
#include "studenti.h"

void set(Student & sa, int n);

const int pupils = 3;
const int quizzes = 5;

int main(void)
{
	Student ada[pupils] = {quizzes, quizzes, quizzes};

	for (int i = 0; i < pupils; i++)
		set(ada[i], quizzes);
	for (i = 0; i < pupils; i++)
	{
		cout << "\n" << ada[i];
		cout << "average: " << ada[i].average() << "\n";
	}
	return 0;
}

void set(Student & sa, int n)
{
	cout << "Please enter the student's name: ";
	cin >> sa;
	cout << "Please enter " << n << " quiz scores:\n";
	for (int i = 0; i < n; i++)
		cin >> sa[i];
	while (cin.get() != '\n')
		continue;
}



Class Templates



// stacktp.h

#include "booly.h"

template 
class Stack
{
private:
	enum {MAX = 10};	// constant specific to class
	Type items[MAX];	// holds stack items
	int top;		// index for top stack item
public:
	Stack();
	Bool isempty();
	Bool isfull();
	Bool push(const Type & item);	// add item to stack
	Bool pop(Type & item);	// pop top into item
};

template 
Stack::Stack()
{
	top = 0;
}

template 
Bool Stack::isempty()
{
	return top == 0? True: False;
}

template 
Bool Stack::isfull()
{
	return top == MAX? True :False;
}

template 
Bool Stack::push(const Type & item)
{
	if (top < MAX)
	{
		items[top++] = item;
		return True;
	}
	else
		return False;
}

template 
Bool Stack::pop(Type & item)
{
	if (top > 0)
	{
		item = items[--top];
		return True;
	}
	else
		return False;
}



// stacktem.cpp -- test template stack class

// compiler with strng2.cpp
#include <iostream.h>
#include <ctype.h>
#include "stacktp.h"
#include "strng2.h"
int main(void)
{
	Stack st;	// create an empty stack
	char c;
	String po;
	cout << "Please enter A to add a purchase order,\n"
		 << "P to process a PO, or Q to quit.\n";
	while (cin >> c && toupper(c) != 'Q')
	{
		while (cin.get() != '\n')
			continue;
		if (!isalpha(c))
		{
			cout << '\a';
			continue;
		}
		switch(c)
		{
			case 'A':
			case 'a':	cout << "Enter a PO number to add: ";
					cin >> po;
					if (st.isfull())
						cout << "stack already full\n";
					else
						st.push(po);
					break;
			case 'P':
			case 'p':	if (st.isempty())
						cout << "stack already empty\n";
					else {
						st.pop(po);
						cout << "PO #" << po << " popped\n";
						break;
						}
		}
		cout << "Please enter A to add a purchase order,\n"
			 << "P to process a PO, or Q to quit.\n";
	}
	cout << "Bye\n";
	return 0;
}



// stcktp1.h

#include "booly.h"

template 
class Stack
{
private:
	enum {MAX = 10};	// constant specific to class
	int stacksize;
	Type * items;		// holds stack items
	int top;			// index for top stack item
public:
	Stack(int ss = MAX);
	~Stack() { delete [] items; }
	Bool isempty() { return top == 0? True: False; }
	Bool isfull() { return top == stacksize? True :False; }
	Bool push(const Type & item);	// add item to stack
	Bool pop(Type & item);			// pop top into item
};

template 
Stack::Stack(int ss) : stacksize(ss), top(0)
{
	items = new Type [stacksize];
}

template 
Bool Stack::push(const Type & item)
{
	if (top < stacksize)
	{
		items[top++] = item;
		return True;
	}
	else
		return False;
}

template 
Bool Stack::pop(Type & item)
{
	if (top > 0)
	{
		item = items[--top];
		return True;
	}
	else
		return False;
}



// stkoptr1.cpp -- test stack of pointers

#include <iostream.h>
#include <stdlib.h>		// for rand(), srand()
#include <time.h>		// for time()
#include "stcktp1.h"
const int Stacksize = 4;
const int Num = 10;
int main(void)
{
	srand(time(0));	// randomize rand()
	cout << "Please enter stack size: ";
	int stacksize;
	cin >> stacksize;
	Stack st(stacksize); // create an empty stack with 4 slots


	char * in[Num] = {
			" 1: Hank Gilgamesh", " 2: Kiki Ishtar",
			" 3: Betty Rocker", " 4: Ian Flagranti",
			" 5: Wolfgang Kibble", " 6: Portia Koop",
			" 7: Joy Almondo", " 8: Xaverie Paprika",
			" 9: Juan Moore", "10: Misha Mache"
			};
	char * out[Num];

	int processed = 0;
	int nextin = 0;
	while (processed < Num)
	{
		if (st.isempty())
			st.push(in[nextin++]);
		else if (st.isfull())
			st.pop(out[processed++]);
		else if (rand() % 2  && nextin < Num)	// 50-50 chance
			st.push(in[nextin++]);
		else
			st.pop(out[processed++]);
	}
	for (int i = 0; i < Num; i++)
		cout << out[i] << "\n";

	cout << "Bye\n";
	return 0;
}



//arraytp.h  -- Array Template


template 
class ArrayTP
{
private:
	T ar[n];
public:
	ArrayTP();
	ArrayTP(const T & v);
	virtual T & operator[](int i) { return ar[i]; }
	virtual const T & operator[](int i) const { return ar[i]; }
};

template 
ArrayTP::ArrayTP()
{
	for (int i = 0; i < n; i++)
		ar[i] = 0;
};

template 
ArrayTP::ArrayTP(const T & v)
{
	for (int i = 0; i < n; i++)
		ar[i] = v;
};



// worker.h  -- working classes

#include "strng2.h"

class Worker
{
private:
	String fullname;
	long id;
protected:
	virtual void data() const;
public:
	Worker() : fullname("no one"), id(0L) {}
	Worker(const String & s, long n)
			: fullname(s), id(n) {}
	virtual void set();
	virtual void show() const;
};

class Waiter : public Worker
{
private:
	int panache;
protected:
	void data() const;
public:
	Waiter() : Worker(), panache(0) {}
	Waiter(const 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 SingingWaiter : public Waiter
{
protected:
	enum {other, alto, contralto, soprano,
					bass, baritone, tenor};
	enum {Vtypes = 7};
	void data() const;
private:
	static char *pv[Vtypes];	// string equivs of voice types
	int voice;
public:
	SingingWaiter() : Waiter(), voice(other) {}
	SingingWaiter(const String & s, long n, int p = 0, int v = other)
			: Waiter(s, n, p), voice(v) {}
	SingingWaiter(const Worker & wk, int p = 0, int v = other)
			: Waiter(wk,p), voice(v) {}
	SingingWaiter(const Waiter & wt, int v = other)
			: Waiter(wt), voice(v) {}
	void set();
	void show() const;
};



// worker.cpp -- working class methods

#include "worker.h"
#include <iostream.h>
// Worker methods
void Worker::set()
{
	cout << "Enter worker's name: ";
	cin >> fullname;
	cout << "Enter worker's ID: ";
	cin >> id;
	while (cin.get() != '\n')
		continue;
}

void Worker::show() const
{
	cout << "Category: worker\n";
	data();
}

// protected method
void Worker::data() const
{
	cout << "Name: " << fullname << "\n";
	cout << "Employee ID: " << id << "\n";
}

// Waiter methods
void Waiter::set()
{
	Worker::set();
	cout << "Enter waiter's panache rating: ";
	cin >> panache;
	while (cin.get() != '\n')
		continue;
}

void Waiter::show()  const
{
	cout << "Category: waiter\n";
	data();
}

// protected method
void Waiter::data() const
{
	Worker::data();
	cout << "Panache rating: " << panache << "\n";
}

// SingingWaiter methods

char * SingingWaiter::pv[] = {"other", "alto", "contralto",
			"soprano", "bass", "baritone", "tenor"};

void SingingWaiter::set()
{
	Waiter::set();
	cout << "Enter number for singer's vocal range:\n";
	for (int i = 0; i < Vtypes; i++)
	{
		cout << i << ": " << pv[i] << "   ";
		if ( i % 4 == 3)
			cout << '\n';
	}
	if (i % 4 != 0)
		cout << '\n';
	cin >>  voice;
	while (cin.get() != '\n')
		continue;
}

void SingingWaiter::show() const
{
	cout << "Category: singing waiter\n";
	data();
}

// protected method
void SingingWaiter::data() const
{
	Waiter::data();
	cout << "Vocal range: " << pv[voice] << "\n";
}


// workarr.cpp -- array of workers

// compile with worker.cpp
#include <iostream.h>
#include <string.h>
#include "worker.h"
#include "arraytp.h" 	// omit if templates not implemented
const int SIZE = 5;
int main(void)
{
	ArrayTP lolas;
	// if no templates, omit the above line and use the one below
	// Worker * lolas[SIZE];

	for (int ct = 0; ct < SIZE; ct++)
	{
		char choice;
		cout << "Enter the employee category:\n"
			<< "e: worker  w: waiter  s: singing waiter  "
			<< "q: quit\n";
		cin >> choice;
		while (strchr("ewsq", choice) == NULL)
		{
			cout << "Please enter an e, w, s, or q: ";
			cin >> choice;
		}
		if (choice == 'q')
			break;
		switch(choice)
		{
			case 'e':	lolas[ct] = new Worker;
						break;
			case 'w':	lolas[ct] = new Waiter;
						break;
			case 's':	lolas[ct] = new SingingWaiter;
						break;
		}
		cin.get();
		lolas[ct]->set();
	}

	cout << "\nHere is your staff:\n";
	for (int i = 0; i < ct; i++)
	{
		cout << '\n';
		lolas[i]->show();
	}
	for (i = 0; i < ct; i++)
		delete lolas[i];
	return 0;
}



// pairs.cpp -- define and use a Pair template

#include <iostream.h>

template 
class Pair
{
private:
	T1 a;
	T2 b;
public:
	T1 & first(const T1 & f);
	T2 & second(const T2 & s);
	T1 first() const { return a; }
	T2 second() const { return b; }
	Pair(const T1 & f, const T2 & s) : a(f), b(s) { }
};

template
T1 & Pair::first(const T1 & f)
{
	a = f;
	return a;
}
template
T2 & Pair::second(const T2 & s)
{
	b = s;
	return b;
}

int main(void)
{
Pair ratings[4] =
			{	Pair("The Purple Duke", 5),
				Pair("Jake's Frisco Cafe", 4),
				Pair("Mont Souffle", 5),
				Pair("Gertie's Eats", 3)
			};

	int joints = sizeof(ratings) / sizeof (Pair);
	cout << "Rating:\t Eatery\n";
	for (int i = 0; i < joints; i++)
		cout << ratings[i].second() << ":\t " <<
				ratings[i].first() << "\n";

	ratings[3].second(6);
	cout << "Oops! Revised rating:\n";
	cout << ratings[3].second() << ":\t " << ratings[3].first() << "\n";

	return 0;
}



Multiple Inheritance




// workerfd.h  -- working classes, first draft
#include "strng2.h"

class Worker
{
private:
	String fullname;
	long id;
protected:
	virtual void data() const;
public:
	Worker() : fullname("no one"), id(0L) {}
	Worker(const String & s, long n)
			: fullname(s), id(n) {}
	virtual void set();
	virtual void show() const;
};

class Waiter : public Worker
{
private:
	int panache;
protected:
	void data() const;
public:
	Waiter() : Worker(), panache(0) {}
	Waiter(const 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 : public Worker
{
public:
	enum {Vtypes = 7};
protected:
enum {other, alto, contralto, soprano,
					bass, baritone, tenor};
private:
	static char *pv[Vtypes];	// string equivs of voice types
	int voice;
protected:
	void data() const;
public:
	Singer() : Worker(), voice(other) {}
	Singer(const 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;
};



// workermi.h  -- working classes

#include "strng2.h"

class Worker
{
private:
	String fullname;
	long id;
protected:
	virtual void data() const;
	virtual void get();
public:
	Worker() : fullname("no one"), id(0L) {}
	Worker(const String & s, long n)
			: fullname(s), id(n) {}
	virtual void set();
	virtual void show() const;
};

class Waiter : virtual public Worker
{
private:
	int panache;
protected:
	void data() const;
	void get();
public:
	Waiter() : Worker(), panache(0) {}
	Waiter(const 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 char *pv[Vtypes];	// string equivs of voice types
	int voice;
public:
	Singer() : Worker(), voice(other) {}
	Singer(const 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;
};

class SingingWaiter : public Singer, public Waiter
{ 
protected:
	void data() const;
	void get();
public:
	SingingWaiter()  {}
	SingingWaiter(const String & s, long n, int p = 0,
							int v = Singer::other)
			: Worker(s,n), Waiter(s, n, p), Singer(s, n, v) {}
	SingingWaiter(const Worker & wk, int p = 0, int v = Singer::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;
};



// workermi.cpp -- working class methods

#include "workermi.h"
#include <iostream.h>
// Worker methods
void Worker::set()
{
	cout << "Enter worker's name: ";
	get();

}

void Worker::show() const
{
	cout << "Category: worker\n";
	data();
}

// protected methods
void Worker::data() const
{
	cout << "Name: " << fullname << "\n";
	cout << "Employee ID: " << id << "\n";
}

void Worker::get()
{
	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 << "\n";
}

void Waiter::get()
{
	cout << "Enter waiter's panache rating: ";
	cin >> panache;
	while (cin.get() != '\n')
		continue;
}

// Singer methods

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] << "\n";
}

void Singer::get()
{
	cout << "Enter number for singer's vocal range:\n";
	for (int i = 0; i < Vtypes; i++)
	{
		cout << i << ": " << pv[i] << "   ";
		if ( i % 4 == 3)
			cout << '\n';
	}
	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();
}



// workmi.cpp -- multiple inheritance

// compile with workermi.cpp, strng2.cpp
#include <iostream.h>
#include <string.h>
#include "workermi.h"
#include "arraytp.h"  // omit if no template support
const int SIZE = 5;
int main(void)
{
	ArrayTP lolas;
	// if no template support, omit the above and use the following:
	// Worker * lolas[SIZE];

	for (int ct = 0; ct < SIZE; ct++)
	{
		char choice;
		cout << "Enter the employee category:\n"
			<< "e: worker  w: waiter  s: singer  "
			<< "t: singing waiter  q: quit\n";
		cin >> choice;
		while (strchr("ewstq", choice) == NULL)
		{
			cout << "Please enter an e, w, s, t, or q: ";
			cin >> choice;
		}
		if (choice == 'q')
			break;
		switch(choice)
		{
			case 'e':	lolas[ct] = new Worker;
						break;
			case 'w':	lolas[ct] = new Waiter;
						break;
			case 's':	lolas[ct] = new Singer;
						break;
			case 't':	lolas[ct] = new SingingWaiter;
						break;
		}
		cin.get();
		lolas[ct]->set();
	}

	cout << "\nHere is your staff:\n";
	for (int i = 0; i < ct; i++)
	{
		cout << '\n';
		lolas[i]->show();
	}
	for (i = 0; i < ct; i++)
		delete lolas[i];
	return 0;
}