CS245 - Comp Sci II

Chapter 8 - Inheritance

Encapsulation - binding code and data into a single structure while hiding the implementation details

Inheritance- The ability to create new objects that maintain the properties & behaviors of ancestor objects

SuperClass & SubClass relationship - "is an"

Inherit everything you can.

Add or change only what you must.

8.1 HIERARCHY AND INHERITANCE

                                    Animals
                              /         |         \
                  Protozoa  Metazoa  Parazoa
                                   /         \
                     Anthropoda      Chordata
                                        /           |
                        Vertebrata         Cephalocordata
                        /            |
            Mammals          Reptilia
                     |
                 Primates
                 / 
    HomoSapiens

8.2 BASE AND DERIVED CLASSES

Base class - superclass

Derived class - subclass

int left, top, bottom, right;

void Draw();

void Erase();

void Move(int h, int v);

		GeometricObject
		/ 	  \
	One_D_Object  Two_D_Object
	/  	\   		/  		\
Line  	Arc  	Rectangle  	Ellipse
				|  		|
			Square  		Circle
Design Guideline 7. If two or more classes are logically related and share member functions and data, consider "factoring out" the common elements of the base class.

class GeometricObject

{

public:

int left, right, top, bottom;

void Draw();

void Erase();

void Move(int h, int v);

};

class Two_D_Object : public GeometricObject

{

public:

int fillPattern;

};

class Rectangle : public Two_D_Object

{

};

cout << thisRect.top;

thisRect.Move(32, -6);

thisRect.fillPattern = 1;

To declare a class to be derived from a base class, follow its name by the name of the base class, as
class DerivedClassName : public BaseClassName

The derived class will have access to all public member data and functions of the base class, just as if they were public members of the derived class.

8.3 INHERITANCE AND ACCESS CONTROL

Public vs. Protected vs. Private

If a data item is declared to be private to a base class, it is inaccessible to any external classes--including those that are derived from the base class.

Class Two_D_Object : public GeometricObject

{

public:

int fillPattern;

void findCenter(int&, int&);

};

findCenter can access top, bottom, left and right because they are public.

Class member functions and data that are declared protected may be accessed by objects of that class, by friends of the class, and by objects in a derived class, but they may not be accessed by any other object.

class GeometricObject

{

public:

void Draw();

void Erase();

void Move(int h, int v);

protected:

int left, right, top, bottom;

private:

};

8.4 CREATING AND DESTROYING DERIVED CLASSES

class GeometricObject
{
public:
	void Draw();
	void Erase();
	void Move(int h, int v);
	GeometricObject();
	GeometricObject(int tp, int lef, int bot, int righ);
protected:
	int left, right, top, bottom;
private:
};

class Two_D_Object : public GeometricObject
{
public:
	void findCenter(int&, int&);
	Two_D_Object();
	Two_D_Object(int tp, int lef, int bot, int righ, int fill) :	GeometricObject( tp, lef, bot, righ);
										//initialization list
protected:
	int fillPattern;
};
class Rectangle : public Two_D_Object
{
public:
	Rectangle();
	Rectangle(int tp, int lef, int bot, int righ, int fill) : Two_D_Object( tp, lef, bot, righ, fill);
};

8.5 DEFINING DERIVED CLASSES

Polymorphism- calls to functions of an object will call code appropriate to whatever instance is actually in the object.

(Use the same function name to represent different "versions" of a function)

void GeometricObject::Draw()
// readies the area to be drawn
{
:
}


void Two_D_Object::Draw()
{
	GeometricObject::Draw();	// call the inherited function
	:
	// set the fill
}

void Rectangle::Draw()
{
	//do some processing
	Two_D_Object::Draw();
	// call the base class and then do the actual drawing
}

main()
{
	GeometricObject geo1;
	Two_D_Object two1;
	Rectangle r1;

	geo1.Draw();
	two1.Draw();
	r1.Draw();
}

PROBLEM - WANT TO DRAW DIFFERENT TYPES OF OBJECTS

GeometricObject GO[10];

:

for (int I = 0; I < numberOfObjects; I++)    GO[i].Draw();

only uses Draw for base class

SOLUTION - use virtual functions and pointers to the objects

virtual void Draw() = 0;

	GeometricObject* GO[numberOfObjects];

	Rectangle r;
	Circle c;
	Line l;

	GO[0] = &r;
	GO[1] = &c;
	GO[2] = &l;

	for (int I = 0; I < numberOfObjects; I++)
		GO[i]->Draw();

heterogeneous lists virtual functions

Step 1: Create an array of objects from the base class.
Step 2: Create individual, derived objects of each derived class.
Step 3: Put the addresses of the derived objects into the array.
Step 4: Access the collection of elements by iterating through the array.
Step 5: Change the declaration of the function to be overridden in the most abstract class by including virtual.

8.6 PROGRAM IN PROGRESS: A PAYROLL PROGRAM

Employee - everyone who receives a paycheck rom the company

name, address, SSN, net pay

Temporary - paid at hourly rate for hrs worked & no payroll deduction

Permanent - fixed deduction

Permanent Hourly - paid at hourly rate for hrs worked

Declaration: The File "EMPLOYEE.H"

// ­­­­­­­­­­EMPLOYEE.H­­­­­­­­­­

// Declarations for class Employee and its derived classes. Class Employee has two directly 

// derived subclasses, Temporary (employees who work on an hourly 
// basis and get no company 
// benefits) and Permanent. Permanent employees (all of whom have a benefit deduction) are 
// further subdivided into Hourly and Salaried classes.

#ifndef _EMPLOYEE_H
#define _EMPLOYEE_H

class Employee // the information common to all employees
{
public:
	virtual void PrintCheck()=0; // a virtual function that will be implemented for each derived class
protected: 					// accessible to derived classes only
	float netPay;
	Employee(); 					// default constructor
	Employee(char* n, char* a, char* ssn);	// constructor with parameters
	char name[30];
	char address[80];
	char socSecNumber[9];
};

class Temporary: public Employee
{
public: 		// Public so that they can be invoked from main()
	Temporary(char* n, char* a, char* ssn, float hw, float hr);
	Temporary();
	void PrintCheck();
private: 					// Temporary is an Employee with ...
	float hoursWorked; 		// a number of hours worked, and
	float hourlyRate; 		// an hourly rate of pay
};

class Permanent: public Employee
{
				// This is public so that it can be initialized externally
public: 					// Permanent is an Employee with ...
	static float benefitDeduction; // a fixed deduction for benefits
	// All is protected so that it is only accessible to derived classes
protected:
	Permanent(char* n, char* a, char* ssn);
	Permanent();
	void PrintCheck()=0; // redeclared as virtual, to be implmented
					// in further derived classes
};

class Hourly: public Permanent
{
public: 		// These must be public so that we can use them in main()
	Hourly(char* n, char* a, char* ssn, float hw, float hr);
	Hourly();
	void PrintCheck();
private: 		// Hourly is a Permanent with ...
	float hoursWorked; 	// a number of hours worked, and
	float hourlyRate; 	// an hourly rate
};

class Salaried: public Permanent
{
public: 	// These must be public so that we can use them in main()
	Salaried(char* n, char* a, char* ssn, float wp);
	Salaried();
	void PrintCheck();
private: // Salaried is a Permanent with ...
	float weeklyPay; // a weekly salary
};

#endif

// ­­­­­­­­­­EMPLOYEE.CPP­­­­­­­­­­

// Definition file for class Employee and its derived classes.

#include <iostream.h> 			//for cin, cout
#include <string.h> 			//for strcmp
#include "EMPLOYEE.H" 	//for Employee declarations

float Permanent::benefitDeduction=100.00;

// define static variable  from class Permanent

Employee::Employee()
// The default constructor for class Employee solicits from the
// standard input (keyboard) values for the data common to all employees.

{
cout << "\nType employee name, followed by <Enter>: ";
cin >> name;
cout << "\nType employee address, followed by <Enter>: ";
cin >> address;
cout << "\nType employee social security number, followed by <Enter>: ";
cin >> socSecNumber;
};


Employee::Employee(char* n, char* a, char* ssn)
// This constructor is used when any kind of employee object is created with supplied parameters.

{
	strcpy(name,n);
	strcpy(address,a);
	strcpy(socSecNumber,ssn);
};

Temporary::Temporary()
// This is the default constructor for a Temporary employee. It solicits
// values from the user for the hours worked and hourly rate.

{
cout << "\nType number of hours worked, followed by <Enter>: ";
cin >> hoursWorked;
cout << "\nType hourly rate, followed by <Enter>: ";
cin >> hourlyRate;
};

Temporary::Temporary(char* n, char* a, char* ssn, float hw, float hr) :
				Employee(n, a, ssn)

// This is the constructor for Temporaries declared with parameters.
// It invokes the Employee constructor to retrieve the basic employee data.
{
	hoursWorked=hw;
	hourlyRate=hr;
};


void Temporary::PrintCheck()

// Calculates the pay for a Temporary, invokes the Employee printCheck
// function to display the basics, and fills in the rest of the check.
{
	netPay = hoursWorked * hourlyRate;
	cout << "\n\n________________________________________________________";
	cout << "\n\nPAY TO THE ORDER OF: " << '\t' << name;
	cout << "\n\t\t\t" << address; 
	cout << "\n\t\t\t" << socSecNumber << '\n';
	cout << "\nEMPLOYEE CLASS: Temporary";
	cout << "\n\nHOURS: " << hoursWorked;
	cout << "\nRATE: " << hourlyRate;
	cout << "\n\nTHE AMOUNT OF ***************************$" << netPay << '\n';
	cout << "\n\n________________________________________________________\n\n";
};

Permanent::Permanent()
{
// the value of static member benefitDeduction is supplied above
}

Permanent::Permanent(char* n, char* a, char* ssn) :
		Employee(n, a, ssn)

// The parameterized constructor for Permanent employees merely invokes
// the Employee constructor to fill in the rest of the employee data.
{
// the value of static member benefitDeduction is supplied above
}

Hourly::Hourly()
// The default constructor for Hourly employees. This solicits values
// for the number of hours worked and the hourly rate.
{
cout << "\nType number of hours worked, followed by <Enter>: ";
cin >> hoursWorked;
cout << "\nType hourly rate, followed by <Enter>: ";
cin >> hourlyRate;
};

Hourly::Hourly(char* n, char* a, char* ssn, float hw, float hr) :
		Permanent(n, a, ssn)
// The parameterized constructor for Hourly employees. This function first invokes the Permanent 
// employee constructor (which, in turn, invokes the Employee constructor) to fill in the Permanent 
// employee data, and then fills in the hourly information from its parameters.
{
	hoursWorked = hw;
	hourlyRate = hr;
};

void Hourly::PrintCheck()
// Prints an Hourly employee's check by: calculating the net pay, calling the printCheck function for
// Permanent employees, and then printing the rest of the check.
{
	netPay=(hoursWorked*hourlyRate)­benefitDeduction;
	cout << "\n\n________________________________________________________";
	cout << "\n\nPAY TO THE ORDER OF: " << '\t' << name;
	cout << "\n\t\t\t" << address; 
	cout << "\n\t\t\t" << socSecNumber << '\n';
	cout << "\nEMPLOYEE CLASS: Hourly";
	cout << "\n\nBENEFITS DEDUCTION: " << benefitDeduction;
	cout << "\nHOURS: " << hoursWorked;
	cout << "\nRATE: " << hourlyRate;
	cout << "\n\nTHE AMOUNT OF ***************************$" << netPay << '\n';
	cout << "\n\n________________________________________________________\n\n";
};

Salaried::Salaried()
// The default constructor for Salaried employees. This function solicits and records a value for the
// weekly salary. The other member data for salaried employees is solicited by the constructors
// for Permanent and Employee classes, which are invoked implicitly.
{
	cout << "\nType weekly salary, followed by <Enter>: ";
	cin >> weeklyPay;
};

Salaried::Salaried(char* n, char* a, char* ssn, float wp) :
		Permanent(n, a, ssn)
// To construct a Salaried employee using parameters, we explicitly invoke the Permanent 
// constructor, and then fill in the value for weekly pay.
{
	weeklyPay = wp;
};

void Salaried::PrintCheck()
// This function calculates the net pay, prints the "Permament" employee
// part of the check, and fills in the data for the Salaried employee.
{
	netPay = weeklyPay­benefitDeduction;
	cout << "\n\n________________________________________________________";
	cout << "\n\nPAY TO THE ORDER OF: " << '\t' << name;
	cout << "\n\t\t\t" << address; 
	cout << "\n\t\t\t" << socSecNumber << '\n';
	cout << "\nEMPLOYEE CLASS: Salaried";
	cout << "\n\nBENEFITS DEDUCTION: " << benefitDeduction;
	cout << "\nSALARY: " << weeklyPay;
	cout << "\n\nTHE AMOUNT OF ***************************$" << netPay << '\n';
	cout << "\n\n________________________________________________________\n\n";
};

// ­­­­­­­­­­­PIP8.CPP­­­­­­­­­­

// Main program to test class Employee and its derived classes.
#include <iostream.h> 					// for cin, cout
#include "EMPLOYEE.H" 			// for Employee classes
#include "UTILITY.H" 				// for SetNumeric, WaitForUser, Terminate
#include <conio.h> 					// for clrscr  ***IMPLEMENTATION DEPENDENT***

inline void ClearScreen() {clrscr();};			//***IMPLEMENTATION DEPENDENT***

void main()

{
	ClearScreen();

		// Create an array to hold (pointers to) our Employees
	Employee* pip8Emps[6];

		// Creating checks via intitialized declarations and place them in our array
	cout << "\n\nCreating a temporary employee pay record . . .";
	Temporary t("Clipper Decker","Clinton, NY","123456789",40.0,5.25);
	pip8Emps[0]=&t;

	WaitForUser();

	cout << "\n\nCreating an hourly employee pay record . . .";
	Hourly h("Sparky Hirshfield","Deansboro, NY","234567890",30.5,8.50);
	pip8Emps[1]=&h;
	
	WaitForUser();

	cout << "\n\nCreating a salaried employee pay record . . .";
	Salaried s("Fenton Sugarman","Boston, MA","345678901",500.00);
	pip8Emps[2]=&s;

	WaitForUser();

		// Creating checks using our interactive constructors, and place them in our array
	cout << "\n\nEnter data for a temporary employee pay record . . .";
	Temporary* tEmp = new Temporary;
	pip8Emps[3]=tEmp;

	cout << "\n\nEnter data for an hourly employee pay record . . .";
	Hourly* hEmp = new Hourly;
	pip8Emps[4]=hEmp;

	cout << "\n\nEnter data for a salaried employee pay record . . .";
	Salaried* sEmp = new Salaried;
	pip8Emps[5]=sEmp;


		// Set format flags for numeric output
	SetNumeric();
	
		// Now, print all checks, letting C++ determine the appropriate version of PrintCheck 
		// depending upon the type of the Employee

	for (int i = 0; i < 6; i++)
	{ 
		ClearScreen();
		pip8Emps[i]­>PrintCheck();
		cout << "\n\n\n";
		WaitForUser();
	};
Terminate();
};

Exercises