#include <iostream>
#include <string>
#include <iomanip>

using namespace std;

//The task:

//Have a generic person class for employees, and two pay categories:
//   Salaried, for people getting an annual salary (based on 52 weeks)
//   Hourly, for people getting an hourly rate based on so many hours per week
//     (with the number of hours fixed)

//Specs:
//  1)  getPay should work appropriately for each child class
//  2)  << should be overloaded in the person class so that name and pay for
//        the week is printed.
//  3)  the person class should have a static function to print table headings
//        for name and pay.

const int WIDTH    = 15;      //Print field width
const int NUMWEEKS = 2;       //Number of weeks in a pay period



//First the abstract base class for the employees

class person
{
friend ostream& operator<< (ostream&, person&);

public:
	person (char* n){name = n;}
	
	string getName (){return name;}
	
	static void doPrintHeadings (ostream& out);  //Column headings

	virtual double getPay () = 0;    //The = 0 makes this an abstract class.  It 
	                                 //  can make no person objects.  Notice:  things 
	                                 //  would work if in the base class the getPay () 
	                                 //  is protected but in the child classes
	                                 //  it is public.  C++doesn't seem to care.  
	                                 //  However, for good practice you should 
	                                 //  be consistent.
protected:

	string name;
};

void person::doPrintHeadings (ostream& out)
{
//Column headings

	out << left  << setw (WIDTH) << "Name" 
	    << right << setw (WIDTH) << "Pay" 
	    << endl  << endl;
}
	
ostream& operator<< (ostream& out, person& it)
{
//Note:  because getPay () is virtual in the person class, the computer will
//  find the getPay () code in the appropriate child class.  (The it object is 
//  either a salaried person or an hourly person.)

	out << setw (WIDTH) << left  << it.getName () 
	
	    << setw (WIDTH) << right << fixed << setprecision (2) << it.getPay ();
	
	return out;
}



//Here is the first child class of the abstract base class person

class salaried:public person
{
public:
	salaried (char* n, double s);
	
	void   setSalary (double s);
	double getPay    ();
	
private:
	int yearlySalary;
};

//In the salaried constructor, notice that the name string n is passed to the
//  constructor of the person base class.

salaried::salaried (char* n, double s):person (n)
{
	yearlySalary = s;
}

void salaried::setSalary (double s)
{
	yearlySalary = s;
}

double salaried::getPay ()
{
	return yearlySalary * NUMWEEKS / 52.;
}



//Here is the second child class of the abstract base class person

class hourly:public person
{
public:	
	hourly (char* n, double r, int h);
	
	void setRate  (double r);
	void setHours (int h);
	
	double getPay ();
	
private:
	double hourlyRate;
	int    hoursPerWeek;
};

//In the hourly constructor, notice that the name string n is passed to the
//  constructor of the person base class.

hourly::hourly (char* n, double r, int h):person (n)
{ 
	hourlyRate   = r; 
	hoursPerWeek = h;
}

void hourly::setRate  (double r)
{
	hourlyRate = r;
}

void hourly::setHours (int h)   
{
	hoursPerWeek = h;
}
	
double hourly::getPay ()
{
	return NUMWEEKS * hourlyRate * hoursPerWeek;
}



//Now the main program that uses the three classes:

int main ()
{
	const int NUMPERSONS = 5;   //To avoid magic numbers
	
	person *people [NUMPERSONS];
	
	people [0] = new salaried ("george", 30000.); //30000 = yrly salary
	people [1] = new hourly   ("max", 20.00, 35); //20  = weekly pay rate,
	                                              //35  = hours per week (same 
	                                              //  each week)
	                                             
	people [2] = new salaried ("julie",    40000.);
	people [3] = new hourly   ("janie",    35.00, 20);
	people [4] = new salaried ("lorraine", 80000.);
	
	person::doPrintHeadings (cout);    //Note the function belongs to the class,
	                                   //  not the objects.  So it must be static.
	
	for (int n = 0; n < NUMPERSONS; n++)
		cout << *people [n] << endl;   //Note the * is necessary because 
                                       //  people[n]
		                               //  is a pointer.
	
	for (int n = 0; n < NUMPERSONS; n++)
		delete people [n];              //What one takes from memory one should return.
	
	return 0;
}

//Here is the printed output that results:

/*
Name                       Pay

george                 1153.85
max                    1400.00
julie                  1538.46
janie                  1400.00
lorraine               3076.92
*/


File translated from TEX by TTH, version 2.25.
On 20 Nov 2002, 17:28.