Inheritance. Today: Inheritance and derived classes Is-A relationship class hierarchies proper...

Post on 18-Dec-2015

215 views 0 download

Tags:

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