#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.