1 / 26

Inheritance & Polymorphism (aka “Object-Oriented Programming”)

Inheritance & Polymorphism (aka “Object-Oriented Programming”). Inheritance Initialization & Destruction of Derived Objects Protected Members Non-public Inheritance Virtual Function Implementation Virtual Destructors Abstract Base Classes and Interfaces. Inheritance.

bian
Download Presentation

Inheritance & Polymorphism (aka “Object-Oriented Programming”)

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. Inheritance & Polymorphism(aka “Object-Oriented Programming”) • Inheritance • Initialization & Destruction of Derived Objects • Protected Members • Non-public Inheritance • Virtual Function Implementation • Virtual Destructors • Abstract Base Classes and Interfaces

  2. Inheritance • (Public) inheritance implements an “is-a” relationship • access of inherited members doesn’t change • private members of a base class are not accessible in derived class methods • public inheritance is the default for struct • Think “substitutability” • a derived object should be able to “stand-in” via a base pointer • code sharing is just a side effect • Don’t inherit just for code sharing

  3. Object InitializationThe Real Story • The base class constructor(s) run(s) first • in declaration order, if multiple inheritance • you pass arguments to base class constructors only through the member initializer list • if the base class has a default constructor, no explicit initializer is necessary • Then any member objects are initialized • in declaration order • Then the derived class constructor runs • Destruction is the reverse of this process

  4. #include <iostream> using namespace std; struct A { A() {cout << "A::A()\n";} ~A() {cout << "A::~A()\n";} }; struct B { B() {cout << "B::B()\n";} ~B() {cout << "B::~B()\n";} }; struct C : A { C() {cout << "C::C()\n";} ~C() {cout << "C::~C()\n";} B b; }; int main() { C c; } A::A() B::B() C::C() C::~C() B::~B() A::~A()

  5. // Using Initializers #include <iostream> using namespace std; struct A { A(int i) {cout << "A::A(" << i << ")\n";} ~A() {cout << "A::~A()\n";} }; struct B { B(int j) {cout << "B::B(" << j << ")\n";} ~B() {cout << "B::~B()\n";} }; struct C : A { C(int i, int j) : A(i), b(j) { cout << "C::C(" << i << ',' << j << ")\n"; } ~C() {cout << "C::~C()\n";} B b; }; int main() { C c(1,2); }

  6. A::A(1) B::B(2) C::C(1,2) C::~C() B::~B() A::~A()

  7. Protected Members • There is a third access specifier - protected • protected members are accessible through derived objects • Idiom: Protected Constructors • Used to make a class abstract • An alternative to using pure virtual functions

  8. Non-public Inheritance“Secretly” using an implementation • Protected Inheritance • Public members in base sub-objects objects are “downgraded” to protected in derived objects • The base class interface is only exposed to derived classes • Private Inheritance • Public and protected members in base sub-objects objects are “downgraded” to private in derived objects • Known as pure “Implementation Inheritance” • the interface of the base class is not exposed at all • Similar to composition, without explicit forwarding

  9. Name Hiding “Gotcha” • Beware when “overriding” functions in derived classes • Example: Hide.cpp

  10. Name Lookup Rules • 1. Find a scope for the name • A class constitutes a scope • A derived class scope is “nested” in the base class’s scope • 2. Perform overload resolution in that scope • Pick unambiguous “best fit” • 3. Check access permission • Examples: Lookup1-3.cpp

  11. A Lookup Oddity? • Why does the following compile? #include <iostream> #include <string> int main() { std::string s = "hello"; std::cout << s; // Calls std::operator<<(ostream&, const string&); // but I didn’t import or specify it. }

  12. Argument-dependent Lookup (ADL) • States that when looking for a function, it will search the namespace of the parameter(s) as well • Since s is in std, it looks in std for operator<<(ostream&, const string&); • A convenience • “Implicit import”, if you will • Causes weird problems with templates!

  13. The Goal of OOP • To treat all objects as base objects • via a pointer-to-base • But to have their behavior vary automatically • depending on the dynamic type of the object etc. Employee Employee SalariedEmployee SalariedEmployee

  14. Heterogeneous Collections int main() { using namespace std; Employee e("John Hourly",16.50); e.recordTime(52.0); SalariedEmployee e2("Jane Salaried",1125.00); e2.recordTime(1.0); Employee* elist[] = {&e, &e2}; int nemp = sizeof elist / sizeof elist[0]; for (int i = 0; i < nemp; ++i) cout << elist[i]->getName() << " gets " << elist[i]->computePay() << endl; } John Hourly gets 957 Jane Salaried gets 1125

  15. Function Binding • Determines the code that executes for a functions call • Static binding occurs at compile time • what we’re used to • Dynamic binding occurs at run time • what Java and SmallTalk folks are used to • what we want here • determined by the dynamic type of object pointed to

  16. How Virtual Functions Work vtbl for Employee Employee Employee::computePay() vptr name rate timeWorked vtbl for SalariedEmployee SalariedEmployee SalariedEmployee::computePay :: vptr salaryGrade • Each class has a vtbl (pointers to its virtual functions) • Each object has a vptr (points to its class’s vtbl)

  17. Advantages of Dynamic Binding • Client code can just deal with the base type (e.g., Employee*) • Behavior varies transparently according to an object’s dynamic type • Client code remains unchanged when new derived types are created! • No “ripple effect” for maintainers

  18. Derived Destructors • Recall that base class destructors are called automatically when a derived object dies: struct B { ~B() {std::cout << "~B\n";} }; struct D : B // public by default { ~D() {std::cout << "~D\n";} }; int main() { D d; } ~D ~B

  19. Deleting via a Pointer-to-Base int main() { B* pb = new D; delete pb; } ~B // Oops! Derived part not destoyed!

  20. Virtual Destructors • Needed when deleting via a pointer-to-base struct B { virtual ~B() {std::cout << "~B\n";} }; int main() { B* pb = new D; delete pb; } ~D // Fixed! ~B

  21. Virtual Destructors • Destructors can be declared virtual • necessary when a base class pointer or reference refers to a derived class object • if the destructor is not declared virtual, only the base class destructor is called • this may cause a memory leak • Rule: Base classes should always have a virtual destructor • Rule of Thumb: A class that contains a virtual function should also declare a virtual destructor

  22. Abstract Classes • Sometimes a base class is just a conceptual entity • a category, or umbrella for related classes • you won’t instantiate any objects of that type Vehicle Car Truck Bus

  23. Pure Virtual Functions • Abstract classes usually have abstract methods: • “Place holder” member functions to be overridden in derived classes • Don’t need an implementation in the base class • The presence of such a pure virtual function makes its class abstract • Append “= 0” to the function’s declaration

  24. Explicit Interfaces • A grouping of method specifications • Used in COM, CORBA, Java, .NET, good OO design • Specified with only pure virtual functions in C++ • To implement an interface, simply inherit and provide all member function definitions • The client programs to the interface • You can change the implementation transparent to the client • Example: Strategy Design Pattern

  25. Implicit Interfaces • A set of expected operations • a.k.a. “Duck Typing” • If they’re there, things just work • If not, compile error • Example: STL Sequences • Expected interface: • copy constructor • assignment operator • equality operator • Example: STL Container Adaptors

  26. RTTI • Runtime Type Identification • The typeid operator • Returns a type_info object • Include <typeinfo> • Not useful for much • Type name • For built-in and polymorphic types only

More Related