Inheritance Today Inheritance and derived classes IsA relationship

































- Slides: 33

Inheritance

Today: Inheritance and derived classes • Is-A relationship • class hierarchies • proper inheritance • (pure) polymorphism • virtual functions • protected members • inheritance and constructors/destructors

Inheritance and Derived Classes l l Problem domain objects are related Has-A relationship • a Car has: Engine, Transmission, Suspension etc. • usually modeled in C and C++ as composition • classes/structs have other structs as members

Example of an Is-A relationship l Employee • name, hiring date, department l Manager • same behavior (services and state) as employee, plus: • employees managed; level

Implementing Is-A in C struct Employee { name, dept, etc } struct Manager { Employee emp; /* containment */ Employee managed[25]; unsigned level; } l Implemented Is-A as Has-A (containment)

Problems with Is-A implementation l Even though a Manager “object” has everything an Employee has plus more… • Cannot pass a Manager variable where Employee is expected • Same for pointers: Manager* and Employee* • What about a mid-level Manager?

Modeling Is-A in C++: Public Inheritance class Manager : public Employee { // data and methods // unique to Manager } l l Employee - a base class Manager - a derived class

Inheriting methods and data class Employee { get/set. Name(); … } Employee e; Manager m; cout << e. get. Name(); cout << m. get. Name();

Inheriting methods and data l l All Employee public members and methods are retained (inherited) by Manager Employee public methods can be used by Manager as if it were an Employee • easy reuse of code l Constructors, destructors, operator= are not inherited

Access rules for derived classes l l (Public inheritance only) public data and functions remain public private members are not accessible in derived classes. Why? Trivial to defeat encapsulation by deriving a class

Class hierarchies l Typical to discover new relationships between domain objects/new specialized objects class Director : public Manager { Car corporate. Vehicle; … }

Class hierarchies Employee Base type Manager Is-A special kind of Employee Director Is-A special kind of Manager

Class hierarchies Employee Manager Director Temporary

Class hierarchies l Typically “root” object at the top - inverted tree

Proper Inheritance l When is a relationship Is-A? class Rectangle {. . . } class Square : public Rectangle {. . . }

Proper Inheritance class Rectangle { // methods to set height and width } class Square : public Rectangle { // method to set size } l Cannot call set. Height()/set. Width() on a Square

Proper Inheritance l l l Criterion: substitutability An object of class Derived can be substituted for an object of class Base everywhere Not true for Rectangle(Base) and Square (Derived)

Three options l l l allow Square to have different width and height do not guarantee that set. Width()/set. Height work on all Rectangle drop the inheritance relationship

Improper inheritance: another example class Bird { void fly(); … } class Penguin : public Bird { // cannot fly }

Improper inheritance: general case l l A base class with an “extra” capability a derived class can't satisfy. Three options: • make the base class weaker • make the derived class stronger • eliminate the proposed inheritance relationship

Bad way of dealing with improper inheritance l Attempt to determine actual type of object at run-time: if (a shape is actually a Rectangle) process it as a rectangle elseif (a shape is a Square) do not attempt to change W and H separately else ? ? ?

Polymorphic class pointers Employee* eptr; Employee e; Manager m; eptr = &e; eptr = &m; l Similar for references

Polymorphic pointers and references l l A pointer or reference of a Base class can always refer to an object of a Derived class (because a Derived Is-A Base) But not vice versa

Virtual functions l Employee: : print() • print name, department l Manager: : print() • print Employee information + level

Virtual functions class Employee { virtual void print(); … } class Manager { virtual void print(); … }

Virtual functions Employee* eptr; Employee e; Manager m; eptr = &e; eptr->print(); // Employee: : print eptr = &m; eptr->print(); // Manager: : print

Virtual functions l l l Actual function called depends on the dynamic type of the pointer Static vs. dynamic types Virtual functions use late binding

Alternative: explicit type field class Employee { enum Empl. Type { E, M }; Empl. Type type; void print(); … } switch (e->type) { … }

Virtual functions: details l Signatures of virtual functions in base and derived class must exactly match

Prohibiting virtual function resolution Manager: : print() { // print Manager-specific stuff // explicitly call print() from // base class Employee: : print(); }

Inheritance and constructors l Objects are constructed “bottom-up” • base first • then member objects • finally, derived class l Constructor in derived class must call constructor(s) for base and member classes

Inheritance and destructors l Destructor in Derived automatically calls destructor in Base

Summary l Is-A relationship l Access inheritance l class hierarchies l proper inheritance l Virtual functions • Static vs. dynamic type l Inheritance and constructors/destructors