Presentation is loading. Please wait.

Presentation is loading. Please wait.

Polymorphism and Virtual Functions

Similar presentations


Presentation on theme: "Polymorphism and Virtual Functions"— Presentation transcript:

1 Polymorphism and Virtual Functions
Andy Wang Object Oriented Programming in C++ COP 3330

2 A Motivational Example
In the previous example, we may have many sub- categories of Students With many different types of grade reports It would be great to store one list of students, and print out ALL grade reports with a loop Student list[30000]; for (int j = 0; j < size; j++) list[i].GradeReport();

3 Problems… The items in the array are base-class Student objects
Base class objects do not know about subtypes (Grads and Undergrads) No such information is stored in the array Everything in an array needs to be the same type and size The GradeReport function being called is the Student class version Want to call the Grad version for graduate students and Undergrad version for undergraduate students Create separate arrays? Not realistic for many subtypes

4 A Base Class Pointer Property
Normally, a pointer can only point to one type However, there is a special rule for inheritance A pointer to a base class type can be pointed at an object derived from the base class Similarly, a base class reference variable can refer to an object derived from that base class Examples Student s; Grad g; Undergrad u; Student *sp1, *sp2, *sp3; sp1 = &s; // pointing at Student object sp2 = &g; // pointing at Grad object sp3 = &u; // pointing at Undergrad object

5 Heterogeneous List A single array of pointers to a base class
These pointers can point to any objects derived from that base Thus, we have created a list of various types of objects Without breaking the array rules All pointers have the same type—a pointer to the base class All pointers have the same size Student *list[30000]; list[0] = &g; list[1] = &u; list[2] = new Grad;

6 Virtual Functions Which version of GradeReport will be run?
If we have the following: for (j = 0; j < size; j++) list[j]->GradeReport(); This still calls the Student version of GradeReport list[j].GradeReport is bound to the Student version at compile time Compiler cannot guess the version of object at run time If we want to run the correct version at runtime, we need to achieve late (dynamic) binding

7 Virtual Functions The keyword virtual will do the trick
To override a base class function when it is called through a pointer, declare the function to be virtual class Student { public: virtual void GradeReport(); }; Now when GradeReport is called through a base-class pointer, the program will run the appropriate version

8 Example Student s; Grad g; Undergrad u; Student *sp1, *sp2, *sp3; sp1 = &s; // pointing at Student object sp2 = &g; // pointing at Grad object sp3 = &u; // pointing at Undergrad object sp1->GradeReport(); // runs Student’s version sp2->GradeReport(); // runs Grad’s version sp3->GradeReport(); // runs Undergrad’s version

9 Pure Virtual Function Suppose you do not want to do anything for the Student’s version of GradeReport You can omit the definition virtual void GradeReport()=0; A virtual function without a definition is a pure virtual function

10 Abstract Class Any class that has at least one pure virtual function is an abstract class An abstract class cannot be instantiated Abstract classes are generally used as base classes They are intended to be a place to declare data and functions common to classes derived from them Abstract class can still be used to build pointers, to take advantage of virtual functions Example abstract class Shape Shape s; // illegal Shape *sptr; // legel

11 Employee Example er/employee/ Hierarchy of derived classes based on a class called Employee Goal is to store the employee information and handle paycheck printing Notice the virtual PrintCheck function and the building of heterogeneous list

12 employee.h #ifndef _EMPLOYEE_H #define _EMPLOYEE_H class Employee { public: virtual void PrintCheck()=0; protected: float netPay; Employee(); Employee(char *n, char *a, char *ssn); char name[30]; char address[90]; char socSecNumber[12]; };

13 employee.h class Temporary : public Employee { public: Temporary(char *n, char *a, char *ssn, float hw, float hr); Temporary(); void PrintCheck(); private: float hoursWorked; float hourlyRate; };

14 employee.h class Permanent: public Employee { public: static float benefitDeduction; protected: Permanent(char *n, char *a, char *ssn); Permanent(); void PrintCheck()=0; };

15 employee.h class Hourly : public Permanent { public: Hourly(char *n, char *a, char *ssn, float hw, float hr); Hourly(); void PrintCheck(); private: float hoursWorked; float hourlyRate; };

16 employee.h class Salaried: public Permananet { public: Salaried(char *n, char *a, char *ssn, float wp); Salaried(); void PrintCheck(); private: float weeklyPay; }; #endif

17 What’s going on?

18 employee.cpp #include <iostream> #include <cstring> #include “employee.h” using namespace std; float Permanent::benefitDeduction=100.00; Employee::Employee() { cout << “\nType employee name, followed by <Enter>: “; cin.getline(name, 30); cout << “\nType employee address, followed by <Enter>: “; cin.getline(address,80); cout << “\n”type employee social security number, followed by <Enter>: “; cin.getline(socSecNumber, 12); }

19 employee.cpp Employee::Employee(char *n, char *a, char *ssn) { strcpy(name, n); strcpy(address, a); strcpy(socSecNumber, ssn); } Temporary::Temporary() { cout << “\nType number of hours worked, followed by <Enter>: “; cin >> hoursWorked; cout << “\nType hourly rate, followed by <Enter>: “; cin >> hourlyRate;

20 employee.cpp Temporary::Temporary(char *n, char *a, char *ssn, float hw, float hr):Employee(n, a, ssn) { hoursWorked = hw; hourlyRate = hr; }

21 employee.cpp void Temporary::PrintCheck() { 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"; };

22 employee.cpp Permanent::Permanent() { } Permanent::Permanent(char* n, char* a, char* ssn): Employee(n, a, ssn) { } Hourly::Hourly() { cout << "\nType number of hours worked, followed by <Enter>: "; cin >> hoursWorked; cout << "\nType hourly rate, followed by <Enter>: "; cin >> hourlyRate; };

23 employee.cpp Hourly::Hourly(char* n, char* a, char* ssn, float hw, float hr):Permanent(n, a, ssn) { hoursWorked=hw; hourlyRate=hr; };

24 employee.cpp void Hourly::PrintCheck() { 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"; };

25 employee.cpp // Other member data is solicited by the constructors for // Permanent and Employee classes Salaried::Salaried() { cout << "\nType weekly salary, followed by <Enter>: "; cin >> weeklyPay; }; Salaried::Salaried(char* n, char* a, char* ssn, float wp): Permanent(n, a, ssn) { weeklyPay=wp;

26 employee.cpp void Salaried::PrintCheck() { 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"; };

27 utility.h #ifndef _UTILITY_H #define _UTILITY_H void Terminate(); // Ask if the user is ready to quit; return 1 if ‘y’ or ‘Y’ int ReadyToQuit(); // Freeze the screen until the user types a character void WaitForUser(); // Set C++ format flags for numeric output void SetNumeric(void); #endif

28 utility.cpp #include <iosteram> #include <cctype> #include <iomanip> #include “utility.h” using namespace std; void Terminate() { char any; cout << “\nPress ‘x’ followed by ENTER to exit the program…”; cin >> any; cout << “\nPROCESSING COMPLETED … GOOD EYE”; }

29 utility.cpp int ReadyToQuit() { char ans; cout << "\nDo you wish to run the program again (Y for yes, N for no)? "; cin >> ans; ans = toupper(ans); while ((ans !='Y') && (ans!='N')) { cout << "\nPlease answer again with Y or N"; cout << "\n\tRun the program again? "; } return(ans =='N'); // returns 1 when ready to quit

30 utility.cpp void WaitForUser(void) { cout << "\nPress 'c' followed by Enter to continue ..."; char any; cin >> any; cin.get(); // pick up newline cout << '\n'; } void SetNumeric(void) { cout << setw(8) << setprecision(2); cout.setf(ios::fixed, ios::floatfield); cout.setf(ios::showpoint);

31 main.cpp #include <iostream> #include “employee.h” #include “utility.h” using namespace std; int main() { Employee *emps[6]; // array of Employee pointers cout << “\n\nCreating a temporary employee pay record…”; Temporary t(“Clipper Decker”, “Clinton, NY”, “ ”, 40.0, 5.25); emps[0] = &t;

32 main.cpp cout << “\n\nCreating an hourly employee pay record…”; Hourly h(“”Sparky Hirshfield”, “Deansboro, NY”, “ ”, 30.5, 8.5); emps[1] = &j; cout << “\n\nCreating a salaried employee pay record…”; Salaried s(“Fenton Sugarman”, “Boston, MA”, “ ”, ); emps[2] = &s; WaitForUser();

33 main.cpp cout << “\n\nEnter data for a temporary employee pay record…”; Temporary *tEmp = new Temporary(“Bob”, “Here”, “ ”, 45.0, 15.45); emps[3] = tEmp; cout << “\n\n”Enter data for an hourly employee pay record…”; Hourly *hEmp = new Hourly; emps[4] = hEmp; cout << “\n\nEnter data for a salaried employee pay record…”; if (cin.peek() == ‘\n’) cin.get(); emps[5] = new Salaried;

34 main.cpp SetNumeric(); for (int j = 0; j < 6; j++) { cout << “\n\n”; emps[i]->Printcheck(); WaitForUser(); } Terminate(); cout << ‘\n’; return 0;


Download ppt "Polymorphism and Virtual Functions"

Similar presentations


Ads by Google