220 likes | 347 Views
ECE 264 Object-Oriented Software Development. Instructor: Dr. Honggang Wang Spring 2013 Lecture 18: More on inheritance and Polymorphism. Lecture outline. Announcements / reminders Monday Session(April 15) re-scheduled to April 17, Wednesday; Due April 19, Friday, by 5:00 pm
E N D
ECE 264Object-Oriented Software Development Instructor: Dr. Honggang Wang Spring 2013 Lecture 18: More on inheritance and Polymorphism
Lecture outline • Announcements / reminders • Monday Session(April 15) re-scheduled to April 17, Wednesday; Due April 19, Friday, by 5:00 pm • Project Demonstration: April 25 and April 30 • Today • Review inheritance basics • Inheritance examples • Polymorphism ECE 264: Lecture 18
Reviewing inheritance • Can take existing code base and • Produce specialized version • Example: Square is a more specific Rectangle • Add extensions • Example: Manager class we discussed last time adds extra data/functionality to Employee • Existing class: base class • New class: derived class • Reuses data/functions from base class • Inherits (almost) everything • Access permissions for base class members set in base class • Any class can be a base class can have hierarchy • Base class can have multiple derived classes ECE 264: Lecture 18
Constructors and Inheritance • Default constructor for a base class is called automatically in the derived class constructor • Ex: Manager() calls Employee() • Will actually traverse inheritance hierarchy, starting at lowest class • If a derived class needs the parameterized constructor of a base class, it must explicitly invoke it in an initialization list • Manager::Manager(string theName, float thePayRate, bool isSalaried): Employee(theName, thePayRate) { salaried = isSalaried; } ECE 264: Lecture 18
Inheritance: Manager methods • How would you write the Manager pay function? • Here’s where we encounter access, reuse issues • Would like to: • Return payRate if salaried • Call Employee function if not salaried ECE 264: Lecture 18
Protected data • Problem: Manager pay function can’t access private data in Employee class • Solution: third type of access specifier: protected • Protected data in a class can be directly accessed by • Functions within that class • Functions within derived classes of that class • Still effectively private data to outside world ECE 264: Lecture 18
Solution: Manager pay function float Manager::pay(float hrsWorked) { if (salaried) return payRate; else return Employee::pay(hrsWorked); } • If Employee data declared protected, not private, can directly access it in Manager function • Explicitly call Employee version of pay function ECE 264: Lecture 18
Inheritance syntax class BClass { protected: int var1; private: int var2; public: BClass(); BClass(int v1, int v2); int sum(); }; class DClass : public BClass { private: int var3; public: DClass(); Dclass(int v1, int v2, int v3); int sum3(); }; • DClass inherits from BClass • Has same data members, functions • Can add additional data • May not have access • protected data are accessible to derived classes • Still private to outside world ECE 264: Lecture 18
Inheritance example class BClass { protected: int var1; private: int var2; public: BClass(); BClass(int v1, int v2); int sum(); }; class DClass : public BClass { private: int var3; public: DClass(); Dclass(int v1, int v2, int v3); int sum3(); }; • What statements in the program below cause errors? int main() { BClass b1(2,3); DClass d1(3,4,5); int a = b1.sum(); int b = d1.sum(); int c = d1.var1; int d = d1.sum3(); int e = b1.sum3(); return 0; } ECE 264: Lecture 18
Polymorphism • Polymorphism: Code/operations behave differently in different contexts • One example: operator overloading • Inheritance-based polymorphism in form of virtual functions • Add virtual to function declaration in .h file • Why use virtual functions? • One benefit of inheritance: code reuse • Another benefit: Can write generic code that works for (hopefully) many specific cases • Take advantage of fact that derived class “is an” object of base class type (with extra/more specific functions) • Virtual functions enable this second benefit ECE 264: Lecture 18
Virtual functions • For example, a base class Animal could have a virtual function eat. • Derived class Fish would implement eat() differently than derived class Wolf • but you can invoke eat() on any class instance referred to as Animal, and get the eat() behavior of the specific derived class • This allows a programmer to process a list of objects of class Animal, telling each in turn to eat (by calling eat()). ECE 264: Lecture 18
Static binding • All methods are, by default, non-virtual methods. Binding of method call is determined by static type of calling object. Example: Employee e1(“John Smith”, 20); Manager m1(“Bob Jones”, 1500, true); e1 = m1; e1.pay(40); //Calls pay() defined in //Employee ECE 264: Lecture 18
Object pointers & inheritance • Dynamic binding: determine type of object at runtime • With inheritance, pointer to base class supports objects of: • Base class type • Derived class type • Pointers also support dynamic binding! • Allows us to write general code using base class pointers ECE 264: Lecture 18
Static vs. dynamic binding • Methods default to non-virtual type of object determines method called • With virtual method, can use dynamic binding if using pointers or references Example: Employee e1(“John Smith”, 20; Manager m1(“Bob Jones”, 1500, true); Employee *ePtr; e1 = m1; ePtr = &m1; e1.pay(40); // Calls pay() defined in // Employee ePtr->pay(40); // Calls pay() defined in // Manager ECE 264: Lecture 18
References and virtual methods • Remember: passing arguments by reference essentially passes pointer • Can use virtual methods on references • Example: float payAnyone(Employee &e, float h) { return e.pay(h); } int main() { Employee e1(“John Smith”, 20; Manager m1(“Bob Jones”, 1500, true); payAnyone(e1, 40); // Calls pay() defined in // Employee payAnyone(m1, 40); // Calls pay() defined in // Manager return 0; } ECE 264: Lecture 18
Virtual functions and member functions • Calling one member function inside another implicitly uses pointers (and therefore dynamic binding) • If f1 is a function of class C • Calling f1 in another class C function is equivalent to: this->f1(); • Example: assume both Employee & Manager have virtual function printPay(float hoursWorked) void Employee::print(float hoursWorked) { cout << “Name: “ << name << endl; cout << “Pay rate: “ << payRate << endl; printPay(hoursWorked); // Uses dynamic // binding; will call // Manager version in // Manager objects } ECE 264: Lecture 18
Destructors and virtual functions • If a class has virtual functions, the destructor should be virtual • Often use pointers with dynamic allocation: Employee *ePtr; char eType = ‘e’; while (eType != ‘x’) { cin >> eType; if (eType == ‘e’) ePtr = new Employee(“John Smith”, 20); else if (eType == ‘m’) ePtr = new Manager(“Bob Jones”, 1500, true); if (ePtr != NULL) ePtr->print(40); delete ePtr; // Needs virtual destructors to ensure // either ~Employee() or ~Manager() is // called correctly ePtr = NULL; } ECE 264: Lecture 18
Example (functions in red are virtual) If we have: Employee e1(“Bob”,25); Manager m1(“Jim”, 40, true); Employee *ePtr; Manager *mPtr; e1 = m1; ePtr = &m1; mPtr = &m1; Which statements are legal? Which function version gets called (for virtual functions)? e1.isSalaried(); m1.getName(); e1.pay(40); ePtr->pay(40); mPtr->print(40); e1.printPay(40); ECE 264: Lecture 18
Example solution If we have: Employee e1(“Bob”,25); Manager m1(“Jim”, 40, true); Employee* ePtr; Manager *mPtr; e1 = m1; ePtr = &m1; mPtr = &m1; Which statements are legal? Which function version gets called (for virtual functions)? e1.isSalaried(); ILLEGAL m1.getName(); calls Manager.getName() e1.pay(40); calls Employee.pay(40) ePtr->pay(40); calls Manager.pay(40) mPtr->print(40); calls Employee.print(40), which calls Manager.printPay(40) e1.printPay(40); calls Employee.printPay(40) ECE 264: Lecture 18
Exam 2 • Average Score: 85 • STD: 8 • Solutions will be uploaded today ECE 264: Lecture 18
Final notes • Next time • Abstract Classes • Acknowledgements: this lecture borrows heavily from lecture slides provided with the following texts: • Deitel & Deitel, C++ How to Program, 8th ed. • Etter & Ingber, Engineering Problem Solving with C++, 2nd ed. ECE 264: Lecture 18