inheritance. today: inheritance and derived classes is-a relationship class hierarchies proper...
TRANSCRIPT
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
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
Another relationship: Is-A (also known as Kind-Of• specialization/generalization
Example of an Is-A relationship
Employee• name, hiring date, department
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;
} Implemented Is-A as Has-A
(containment)
Problems with Is-A implementation
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
}
Employee - a base class Manager - a derived class
Inheriting methods and data
class Employee {
get/setName();
…
}
Employee e;
Manager m;
cout << e.getName();
cout << m.getName();
Inheriting methods and data
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
Constructors, destructors, operator= are not inherited
Access rules for derived classes
(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
Typical to discover new relationships between domain objects/new specialized objects
class Director : public Manager {
Car corporateVehicle;
…
}
Class hierarchies
Director
EmployeeEmployee
Manager Is-A special kind of Employee
Is-A special kind of Manager
Base type
Class hierarchies
Director
EmployeeEmployee
Manager Temporary
Class hierarchies
Typically “root” object at the top - inverted tree
Proper Inheritance
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
} Cannot call setHeight()/setWidth() on
a Square
Proper Inheritance
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
allow Square to have different width and height
do not guarantee that setWidth()/setHeight 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
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
Attempt to determine actual type of object at run-time:
if (a shape is actually a Rectangle) process it as a rectangleelseif (a shape is a Square) do not attempt to change W and H separatelyelse ???
Polymorphic class pointers
Employee* eptr;
Employee e;
Manager m;
eptr = &e;
eptr = &m;
Similar for references
Polymorphic pointers and references
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
Employee::print()• print name, department
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
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 EmplType { E, M };
EmplType type;
void print();
…
}
switch (e->type) {
…
}
Virtual functions: details
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
Objects are constructed “bottom-up”• base first• then member objects• finally, derived class
Constructor in derived class must call constructor(s) for base and member classes
Inheritance and destructors
Destructor in Derived automatically calls destructor in Base
Summary
Is-A relationship
Access inheritance
class hierarchies
proper inheritance
Virtual functions
• Static vs. dynamic type
Inheritance and constructors/destructors