1 / 24

Lets recall

Lets recall. What we have seen so far Non-polymorphic inheritance (Object Based) Inheritance for code reuse reasons Reflects a relationship of Is-A Inheritance means that the derived inherits its base class characteristics The derived class can add to this characteristics of its own

madra
Télécharger la présentation

Lets recall

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Lets recall • What we have seen so far • Non-polymorphic inheritance (Object Based) • Inheritance for code reuse reasons • Reflects a relationship of Is-A • Inheritance means that the derived inherits its base class characteristics • The derived class can add to this characteristics of its own • For instance: • The layout of derived contains the layout of the base class Class person name GetName() Class worker salary CalculateSal()

  2. Lets recall • We can invoke all inherited characteristics through the derived • For instance, we can ask the worker what is his name, even though he does not implement such a method Worker w(…); w.GetName(); • The compiler resolves the call to Person::GetName() • If we implement such a method at the Worker class • It will be called (resolved to Worker::GetName()) • Protected access keyword has been introduced

  3. Lets Continue to Polymorphic Inheritance • Suppose we have a container of Employees • We would like to iterate over all employees, without knowing which specific kind they are, and ask them to calculate their salary (call their CalcSalary() method) • Each type has its own calculation algorithm, based on different considerations • Each object will invoke its relevant CalcSalary(), depending on its type Class Employee m_salary v. CalcSalary() Class SalesPerson Class Executive Class Administrative m_sales m_performance v. CalcSalary() v. CalcSalary() v. CalcSalary()

  4. Example Employee* employees[100]; Executive Administrative Executive Administrative Sales Person • We want each element in the container to call its own CalcSalary() method as a function of the real object • Employee  Employee::CalcSalary() • SalesPerson  SalesPerson::CalcSalary() • Executive  Executive::CalcSalary() • Administrative  Administrative::CalcSalary()

  5. Static and dynamic binding • In object-oriented programming languages in most cases the variables are bound to a specific type at compile time • Static binding • Dynamic binding • The type of the variable can change at run time • Using pointers to classes related by inheritance Executive exec; Employee* emp = &exec; • Can be dangerous in some cases

  6. Example • Definition: • Single name denotes objects of different classes related by inheritance • Ability to manipulate derived objects using the interface defined in the base class • Example: class Employee { public: void CalcSalary (); }; class SalariedEmployee :public Employee{ public: void CalcSalary (); };

  7. Example Employee *ep; ep = new SalariedEmployee; ep->CalcSalary(); • Which function is called? • The function in Employee is called • To avoid that we have to declare CalcSalary() as a virtual function • virtual is a special keyword

  8. Virtual Functions • Definition: • Member function prefaced by the virtual specifier. • Compiler generates the code that will select the appropriate function at runtime • Example: class Employee { public: virtual void CalcSalary (); }; class SalariedEmployee:public Employee{ public: virtual void CalcSalary (); }; • virtual specifier needs to appear in the base class only • However, typically specified also in subclusses

  9. Examples Employee *p0 = new Employee; Employee *p1 = new SalariedEmployee; p0->CalcSalary(); // calls Employee::CalcSalary() p1->CalcSalary(); // calls SalariedEmployee::CalcSalary() • Any non-static member function except a constructor can be virtual • Virtual functions can also be friends of other classes • Some compilers require the class destructor to be virtual if a class contains any virtual functions

  10. class A { public: void x() {cout<<"A:x";}; virtual void y() {cout<<"A:y";}; }; class B : public A { public: void x() {cout<<"B:x";}; virtual void y() {cout<<"B:y";}; }; int main () { B b; A *ap = &b; B *bp = &b; b.x (); b.y (); bp->x (); bp->y (); ap->x (); ap->y (); return 0; }; Only matter with pointer or reference Calls on object itself resolved statically b.y(); Look first at pointer/reference type If non-virtual there, resolve statically ap->x(); If virtual there, resolve dynamically ap->y(); Caller can force static resolution of a virtual function via scope operator ap->A::y(); prints “A::y” Virtual Functions // prints "B:x" // prints "B:y" // prints "B:x" // prints "B:y" // prints "A:x" // prints "B:y"

  11. Combinations of virtual and non-virtual functions • Non-virtual function can call virtual function • Example: class Employee { public: void Display(); virtual void CalcSalary (); }; class SalariedEmployee:public Employee{ public: void Display(); virtual void CalcSalary (); };

  12. Example void Employee::Display() { CalcSalary(); }; void SalariedEmployee::Display() { CalcSalary(); }; Employee *p0 = new SalariedEmployee; p0->Display(); // calls SalariedEmployee::CalcSalary();

  13. Example • It works the other way too class Employee { public: virtual void Display(); void CalcSalary (); }; class SalariedEmployee:public Employee{ public: virtual void Display(); void CalcSalary (); }; Employee *p0 = new SalariedEmployee; p0->Display(); // calls Employee::CalcSalary();

  14. Common Interface • Virtual functions in the base class provide common interface for all of its derived classes • Example: class Employee { public: long GetDepartment(); long GetId(); virtual void Display(); virtual void Input (); virtual void CalcSalary (); private: long id; long deptNum; };

  15. Example class Polygon { protected: int width, height; public: void set_values (int a, int b){ width=a; height=b; } virtual int area(); }; class Rectangle: public Polygon { public: int area (void) { return (width * height); } }; class Triangle: public Polygon { public: int area (void) { return (width * height / 2); } };

  16. Example (cont.) int main () { Rectangle rect; Triangle trgl; Polygon * ppoly1 = &rect; Polygon * ppoly2 = &trgl; ppoly1->set_values (4,5); ppoly2->set_values (4,5); cout << ppoly1->area() << endl; cout << ppoly2->area() << endl; return 0; }

  17. Virtual Destructors • Destructor preceded by the virtual specifier • Correct destructor must be called • It is recommended that any class containing virtual functions should also have a virtual destructor • Example • BookItem needs a separate destructor to de-allocate the storage for title class Item { public: virtual ~Item(); //... }; class BookItem { public: virtual ~BookItem(); private: char * title; };

  18. Pure Virtual • The Employee can define this method at the base class as pure virtual : virtual int Employee::CalcSalary() = 0; Meaning, • It wants all inheriting classes to implement their own implementation • We cannot instantiate an object of this class – it is said to be an Abstract Class • But we still can have pointers

  19. Example class Polygon { protected: int width, height; public: void set_values (int a, int b){ width=a; height=b; } virtual int area()=0; }; class Rectangle: public Polygon { public: int area (void) { return (width * height); } }; class Triangle: public Polygon { public: int area (void) { return (width * height / 2); } };

  20. Example (cont.) int main () { Rectangle rect; Triangle trgl; Polygon * ppoly1 = &rect; Polygon * ppoly2 = &trgl; ppoly1->set_values (4,5); ppoly2->set_values (4,5); cout << ppoly1->area() << endl; cout << ppoly2->area() << endl; return 0; }

  21. class A { public: virtual void x() = 0; virtual void y() = 0; }; class B : public A { public: virtual void x(); }; class C : public B { public: virtual void y(); }; int main () { A * ap = new C; ap->x (); ap->y (); delete ap; return 0; }; A is an Abstract Base Class Declares pure virtual functions (=0) Derived classes override pure virtual methods B overrides x(), C overrides y() Can’t instantiate class with declared or inherited pure virtual functions A and B are abstract, can create a C Can still have a pointer to an abstract class type Useful for polymorphism Virtual Functions

  22. Static Binding Vs. Dynamic Binding • Static Binding • Function call is resolved during compile time • CALL fixed value • Dynamic Binding • During compile time we cannot know what address to jump to • It needs to be resolved during run-time • Depending on the type of the actual object • This information is accessed via virtual pointer • Each object holds • And via virtual table • Each class maintains

  23. Dynamic Binding - Implementation Employee* employees[100]; Executive Administrative Executive Administrative Sales Person Executive Virtual Table Executive::CalcSalary() Sales Person Virtual Table SalesPerson::CalcSalary()

  24. Push common code and variables up into base classes Use public inheritance for polymorphism Polymorphism depends on dynamic typing Use a base-class pointer or reference if you want polymorphism Use virtual member functions for dynamic overriding Use private inheritance only for encapsulation Use abstract base classes to declare interfaces Even though you don’t have to, label each virtual method (and pure virtual method) in derived classes Summary: Tips on Polymorphism

More Related