Quick viewing(Text Mode)

The C++ Programming Language Single and Multiple Inheritance In

The C++ Programming Language Single and Multiple Inheritance In

Background

The C++ Programming

 Object-oriented programming is often de-

ned as the combination of Abstract Data

Language

Typ es ADTs with Inheritance and Dy-

namic Binding

Single and in

 Each concept addresses a di erent asp ect

of system decomp osition:

C++

1. ADTs decomp ose systems into two-dimensional

grids of mo dules

{ Each mo dule has public and private inter-

faces

Douglas C. Schmidt

2. Inheritance decomp oses systems into three-dimensional

www.cs.wustl.edu/schmidt/

hierarchies of mo dules

{ Inheritance relationships form a \lattice"

[email protected]

3. Dynamic binding enhances inheritance

Washington University, St. Louis

{ e.g., defer implementation decisions until late

in the design phase or even until run-time!

2 1

Motivation for Inheritance

Data Abstraction vs. Inheritance

 Inheritance allows you to write co de to

DATA ABSTRACTION

certain cases and allows other de- (2 DIMENTIONAL) handle

(2 DIMENTIONAL)

velop ers to write co de that handles more

sp ecialized cases, while your co de contin-

ues to work

 Inheritance partitions a system architec-

ture into semi-disjoint comp onents that

are related hierarchically

 Therefore, we may be able to mo dify and/or

reuse sections of the inheritance hierarchy

without disturbing existing co de, e.g.,

{ Change sibling subtree interfaces

i.e., a consequence of inheritance INHERITANCE 

(3 DIMENTIONAL)

{ Change implementation of ancestors

 i.e., a consequence of data abstraction

3 4

Inheritance Overview

Visualizing Inheritance

 A typ e called a sub class or derived typ e

can inherit the characteristics of another

typ es called a sup erclass or base typ e

Base

The term sub class is equivalent to derived typ e { Derived

2

A derived typ e acts just like the base typ e,

 Derived

for an explicit list of: except 1

Derived

1. Sp ecializations

5

{ Change implementations without changing

base class

the Derived

Most useful when combined with dynamic  Derived 4

binding 3 Derived

6

2. Generalizations/Extensions

{ Add new op erations or data to derived classes

5 6

Typ es of Inheritance

Inheritance Trees vs. Inheritance

DAGs

 Inheritance comes in two forms, dep end-

ing on numb er of parents a sub class has

Single Inheritance SI 1. Base

Derived Derived

Only one parent per derived class

{ 1 2

{ Form an inheritance \"

INHERITANCE Derived

{ SI requires a small amount of run-time over-

when used with dynamic binding head Derived TREE 4

3

{ e.g., , Simula,

2. Multiple Inheritance MI

More than one parent per derived class { Base Base 1

Derived 2

{ Forms an inheritance \Directed Acyclic Graph"

AG

 1

{ Compared with SI, MI adds additional run-

overhead also involving dynamic bind- time INHERITANCE

ing Derived Derived

3 DAG 4

{ e.g., C++, Ei el, Flavors a LISP dialect

7 8

Inheritance Bene ts

Inheritance Liabilities

1. Increase reuse and software quality

1. May create deep and/or wide hierarchies

 Programmers reuse the base classes instead of

that are dicult to understand and navi-

writing new classes

gate without class browser to ols

{ Integrates black-b ox and white-b ox reuse by

allowing extensibility and mo di cation with-

out changing existing co de

2. May decrease p erformance slightly

 Using well-tested base classes helps reduce bugs

 i.e., when combined with multiple inheritance

in applications that use them

and dynamic binding

 Reduce object co de size

3. Without dynamic binding, inheritance has

only limited utility

2. Enhance extensibility and comprehensibil-

ity

 Likewise, dynamic binding is almost totally use-

less without inheritance

 Helps supp ort more exible and extensible ar-

chitectures along with dynamic binding

{ i.e., supp orts the op en/closed principle

4. Brittle hierarchies, which may imp ose de-

 Often useful for mo deling and classifying hierarchically-

p endencies up on ancestor names

related domains

10 9

Key Prop erties of C++

Inheritance

 The base/derived class relationship is ex-

Inheritance in C++

plicitly recognized in C++ by prede ned

standard conversions

{ i.e., a p ointer to a derived class may always be

 Deriving a class involves an extension to

assigned to a p ointer to a base class that was

the C++ class declaration syntax

inherited publically

 But not vice versa:::

 The class head is mo di ed to allow a deriva-

tion list consisting of base classes

 When combined with dynamic binding, this

sp ecial relationship between inherited class

typ es promotes a typ e-secure, p olymor-

phic style of programming

 e.g.,

{ i.e., the programmer need not know the actual

typ e of a class at compile-time

class Foo f /* :::g;

class Bar : public Foo f /* :::g;

{ Note, C++ is not truly p olymorphic

class Foo : public Foo, public Bar f /* :::g;

 i.e., op erations are not applicable to objects

that don't contain de nitions of these op-

erations at some p oint in their inheritance

hierarchy

11 12

Simple Screen Class

Sub classing from Screen

 The following co de is used as the base

class:

 class Screen can be a public base class of

class Window

class Screen f

public:

Screen int = 8, int = 40, char = ' ';

 e.g.,

~Screen void;

short height void const f return this->height ; g

class Window : public Screen f

short width void const f return this->width ; g

public:

= h; g void height short h f this->height

Window const Point &, int rows = 24,

void width short w f this->width = w; g

int columns = 80,

Screen &forward void;

char default char = ' ';

Screen &up void;

void set foreground color Color &;

Screen &down void;

void set background color Color &;

Screen &home void;

void resize int height, int width;

Screen &b ottom void;

// :::

Screen &display void;

private:

Screen © const Screen &;

Point center ;

// :::

Color foreground ;

private:

Color background ;

short height , width ;

// :::

char *screen , *cur pos ;

g;

g;

13 14

The Screen Inheritance Hierarchy

Multiple Levels of Derivation

 A derived class can itself form the basis

for further derivation, e.g.,

Point

Menu : public Window f

class Screen

public:

lab el const char *l; set

void Color

Menu const Point &, int rows = 24,

int columns = 80,

char default char = ' ';

// :::

rivate:

p Window

char *lab el

; Menu

// :::

g;

 class Menu inherits data and metho ds from

b oth Window and Screen

{ i.e., sizeof Menu >= sizeof Window >= sizeof

Screen

 Screen/Window/Menu hierarchy

15 16

Using the Screen Hierarchy

Variations on a Screen: : :

 e.g.,

ps1 :

Screen f public: virtual void dump ostream &; = 0 g

ps2 : class

Window : public Screen f

Screen Screen class

public: virtual void dump ostream &;

g;

class Menu : public Window f

public: virtual void dump ostream &;

g;

// stand-alone function

void dump Screen *s, ostream &o f

w : image

Some pro cessing omitted

Window Menu //

s->dump o;

// *s->vptr[1] s, o;

g

Screen s; Window w; Menu m;

Vector bv; Bit

// OK: Window is a kind of Screen

 A p ointer to a derived class can be as-

dump image &w, cout;

signed to a p ointer to any of its public

// OK: Menu is a kind of Screen

base classes without requiring an explicit

image &m, cout; dump

cast:

// OK: argument typ es match exactly

image &s, cout; dump

Menu m; Window &w = m; Screen *ps1 = &w;

Vector is not a kind of Screen! // Error: Bit

Screen *ps2 = &m;

dump image &bv, cout;

18 17

Sp ecialization Example

Using Inheritance for

Sp ecialization

 Inheritance may be used to obtain the fea-

tures of one data typ e in another closely

 A derived class sp ecializes a base class by

related data typ e

adding new, more sp eci c state variables

and metho ds

 For example, class Date represents an ar-

{ Metho d use the same interface, even though

bitrary Date:

they are implemented di erently

class Date f

 i.e., \overridden"

public:

Date int m, int d, int y;

virtual void print ostream &s const;

// :::

{ Note, there is an imp ortant distinction between

private:

overriding, hiding, and overloading:::

, day , year ; int month

g;

 Class Birthday derives from Date, adding

a name eld representing the p erson's birth-

 A variant of this is used in the template

day, e.g.,

metho d pattern

class Birthday : public Date f

{ i.e., b ehavior of the base class relies on func-

public:

tionality supplied by the derived class

Birthday const char *n, int m, int d, int y

: Date m, d, y, p erson strdup n fg

~Birthday void f free p erson ; g

virtual void print ostream &s const;

{ This is directly supp orted in C++ via abstract

// :::

base classes and pure virtual functions

private:

; const char *p erson

g;

20 19

Alternatives to Sp ecialization

Implementation and Use-case

 Note that we could also use object com-

 Birthday::print could print the p erson's name

p osition instead of inheritance for this ex-

as well as the date, e.g.,

ample, e.g.,

void Birthday::print ostream &s const f

class Birthday f

<< " was born on "; s << this->p erson

public

Date::print s;

Birthday char *n, int m, int d, int y:

s << "\n";

date m, d, y, p erson n fg

g

// same as b efore

private:

; Date date

 e.g.,

; char *p erson

g;

const Date july 4th 7, 4, 1993;

Birthday my birthday "Douglas C. Schmidt", 7, 18, 1962;

 However, in this case we would not be able

to utilize the dynamic binding facilities for

july 4th.print cerr;

base classes and derived classes

// july 4th, 1993

birthday.print cout; my

{ e.g.,

// Douglas C. Schmidt was born on july 18th, 1962

Date *dp = &my birthday;

Date *dp = &my birthday;

// ERROR, Birthday is not a sub class of date!

dp->print cerr;

{ While this do es not necessarily a ect reusabil-

// ??? what gets printed ???

ity, it do es a ect extensibility:::

// *dp->vptr[1]dp, cerr;

21 22

Extension/Generalization

Using Inheritance for

Example

Extension/Generalization

 Using class Vector as a private base class

for derived class Stack

 Derived classes add state variables and/or

op erations to the prop erties and op era-

tions asso ciated with the base class

class Stack : private Vector f /* :::*/ g;

{ Note, the interface is generally widened!

 In this case, Vector's operator[] may be

reused as an implementation for the Stack

{ Data memb er and metho d access privileges may

push and pop metho ds

also be mo di ed

{ Note that using private inheritance ensures that

operator[] do es not show up in the interface

for class Stack!

 Extension/generalization is often used to

faciliate reuse of implementations, rather

than interface

 Often, a b etter approach in this case is

{ However, it is not always necessary or correct

to exp ort interfaces from a base class to de-

to use a comp osition/Has-A rather than

rived classes

a descendant/Is-A relationship:::

24 23

Vector Interface

Vector Implementation

 Using class Vector as a base class for a

Vector derived class such as class Checked

or class Ada Vector

 e.g.,

{ One can de ne a Vector class that implements

template

an unchecked, uninitialized array of elements

t s: size s, buf new T[s] fg Vector::Vector size

of typ e T

template

Vector::~Vector void f delete [] this->buf ; g

 e.g., /* File Vector.h incomplete wrt ini-

tialization and assignment */

t template size

Vector::size void const f return this->size ; g

// Bare-b ones implementation, fast but not safe

template

template T &

class Vector f

t i f return this->buf [i]; g Vector::op erator[] size

public:

Vector size t s;

int main void f

~Vector void;

Vector v 10;

t size void const; size

v[6] = v[5] + 4; // o ops, no initial values

T &op erator[] size t index;

int i = v[v.size ]; // o ops, out of range!

// destructor automatically called

private:

g

T *buf ;

size t size ;

g;

26 25

Bene ts of Inheritance

Vector Interface Checked

 Inheritance enables mo di cation and/or ex-

tension of ADTs without changing the orig-

 The following is a sub class of Vector that

inal source co de

allows run-time range checking:

{ e.g., someone may want a variation on the ba-

sic Vector abstraction:

 /* File Checked-Vector.h incomplete wrt

1. A vector whose b ounds are checked on every

initialization and assignment */

reference

struct RANGE ERROR f

2. Allow vectors to have lower b ounds other

"range error" size t index;

than 0

// :::

3. Other vector variants are p ossible to o:::

g;

template

 e.g., automatically-resizing vectors, initial-

class Checked Vector : public Vector f

ized vectors, etc.

public:

Checked Vector size t s;

T &op erator[] size t i throw RANGE ERROR;

// Vector::size  inherited from base class Vector.

 This is done by de ning new derived classes

that inherit the characteristics of the Vector

protected:

base class

bool in range size t i const;

private:

{ Note that inheritance also allows co de to be

typ edef Vector inherited;

shared

g;

27 28

Implementation of

Checked Vector

Checked Vector Use-case

 e.g.,

 e.g.,

template bool

include "Checked Vector.h"

Checked Vector::in range size t i const f

return i < this->size ;

typ edef Checked Vector CV INT;

g

int fo o int size

template

f

Checked Vector::Checked Vector size t s

try

: inherited s fg

f

INT cv size; CV

template T &

int i = cv[cv.size ]; // Error detected!

Vector::op erator[] size t i Checked

// exception raised:::

ERROR throw RANGE

// Call base class destructor

f

g

if this->in range i

ERROR catch RANGE

return *inherited * this[i];

f /* :::*/ g

// return BASE::op erator[]i;

g

else

throw RANGE ERROR i;

g

29 30

Design Tip

Vector Interface Ada

 Note, dealing with parent and base classes

{ It is often useful to write derived classes that

do not enco de the names of their direct parent

 The following is an Ada Vector example,

class or base class in any of the metho d b o dies

where we can have array b ounds start at

something other than zero

{ Here's one way to do this systematically:

class Base f

 /* File ada vector.h still incomplete wrt

public:

initialization and assignment:: : . */

int fo o void;

g;

class Derived 1 : public Base f

include "vector.h"

typ edef Base inherited;

// Ada Vectors are also range checked!

public:

template

int fo o void f inherited::fo o ; g

class Ada Vector : private Checked Vector f

g;

public:

class Derived 2 : public Derived 1 f

Ada Vector size t l, size t h;

typ edef Derived 1 inherited;

T &op erator size t i throw RANGE ERROR

public:

inherited::size; // explicitly extend visibility

int fo o void f

private:

inherited::fo o ;

g

typ edef Checked Vector inherited;

g;

size t lo bnd ;

g;

{ This scheme obviously do esn't work as trans-

parently for multiple inheritance:::

31 32

Ada Vector Use-case

 Example Ada Vector Usage File main.C

Ada Vector Implementation

include

include

vector.h" include "ada

 e.g., class Ada Vector cont'd

int main int argc, char *argv[] f

template

try f

Ada Vector::Ada Vector size t lo, size t hi

t lower = ::atoi argv[1]; size

bnd lo fg : inherited hi lo + 1, lo

size t upp er = ::atoi argv[2];

Ada Vector ada vec lower, upp er;

template T &

Ada Vector::op erator size t i

ada vec lower = 0;

throw RANGE ERROR f

if this->in range i this->lo bnd 

t i = lower + 1; i <= ada vec.size ; i++ for size

return Vector::op erator[] i this->lo bnd ;

ada vec i = ada vec i 1 + 1;

// or Vector &self = *Vector * this;

bnd ]; // self[i this->lo

// Run-time error, index out of range

else

ada vec upp er + 1 = 100;

throw RANGE ERROR i;

g

// Vector destructor called when

// ada vec go es out of scop e

g

catch RANGE ERROR f /* :::*/ g

g

33 34

Memory Layout

Base Class Constructor

 Memory layouts in derived classes are cre-

ated by concatenating memory from the

base classes

 Constructors are called from the \b ottom

{ e.g., // from the cfront-generated .c le

up"

struct Vector f

6Vector; T *buf

size t size 6Vector;

 Destructors are called from the \top down"

g;

Vector f struct Checked

T *buf 6Vector;

 e.g.,

size t size 6Vector;

g;

Vector f struct Ada

/* Vector constructor */

T *buf 6Vector; // Vector

struct Vector *

t size 6Vector; // part size

ct 6VectorFi struct Vector * 0this, size t 0s f

size t lo bnd 10Ada Vector; // Ada Vector

if  0this jj  0this =

g;

nw FUi sizeof struct Vector

 0this->size 6Vector = 0s,

 0this->buf 6Vector =

 The derived class constructor calls the base

nw FUi sizeof int * 0s;

constructor in the \base initialization sec-

return 0this;

tion," i.e.,

g

Ada Vector::Ada Vector size t lo, size t hi

: inherited hi lo + 1, lo bnd lo fg

35 36

Derived Class Constructors

Destructor

 e.g.,

 Note, destructors, constructors, and as-

Vector constructor */ /* Checked

struct Checked Vector * ct 14Checked VectorFi 

signment op erators are not inherited

struct Checked Vector * 0this, size t 0s f

if  0this jj  0this =

nw FUi sizeof struct Checked Vector

 However, they may be called automati-

0this = ct 6VectorFi  0this, 0s;

cally were necessary, e.g.,

return 0this;

g

dt 6VectorFv  char

/* Ada Vector constructor */

struct Vector * 0this, int 0 free f

struct Ada Vector * ct 10Ada VectorFiT1 

0this f if 

struct Ada Vector * 0this, size t 0lo, size t 0hi f

dl FPv char * 0this->buf 6Vector;

if  0this jj  0this =

if  0this

nw FUi sizeof struct Ada Vector

0 free & 1 if 

0this = ct 14Checked VectorFi  0this, if 

dl FPv char * 0this;

0hi 0lo + 1

g

0this->lo bnd 10Ada Vector = 0lo;

g

return 0this;

g

38 37

Describing Relationships Between

Classes

Has-A vs. Is-A Relationships

 Consumer/Comp osition/Aggregation

{ A class is a consumer of another class when

makes use of the other class's services, as

it CONSUMER DESCENDANT

de ned in its interface

RELATIONSHIP RELATIONSHIP

For example, a Stack implementation could

 Vector

rely on an array for its implementation and

be a consumer of the Array class

thus Stack

Consumers are used to describ e a Has-A rela- { Checked tionship Vector Vector

Ada

Descendant/Inheritance/Sp ecialization

 Vector

{ A class is a descendant of one or more other

classes when it is designed as an extension or

sp ecialization of these classes. This is the no-

tion of inheritance

{ Descendants are used to describ e an Is-A rela-

tionship

39 40

The Dangers of Implementation Interface vs. Implementation

Inheritance Inheritance

 Class inheritance can be used in two pri-

 Using inheritance for reuse may sometimes

mary ways:

be a dangerous misuse of the technique

1. Interface inheritance: a metho d of creating a

{ Op erations that are valid for the base typ e may

subtyp e of an existing class for purp oses of set-

not apply to the derived typ e at all

ting up dynamic binding, e.g.,

 e.g., p erforming an subscript op eration on a

{ Circle is a sub class of Shap e i.e., Is-A rela-

stack is a meaningless and p otentially harm-

tion

ful op eration

{ A Birthday is a sub class of Date

class Stack : public Vector f

// :::

2. Implementation inheritance: a metho d of reusing

g;

an implementation to create a new class typ e

Stack s;

s[10] = 20; // could be big trouble!

{ e.g., a class Stack that inherits from class

Vector. A Stack is not really a subtyp e or

{ In C++, the use of a private base class mini-

sp ecialization of Vector

mizes the dangers

{ In this case, inheritance makes implementa-

 i.e., if a class is derived \private," it is illegal

tion easier, since there is no need to rewrite

to assign the address of a derived object to

and debug existing co de.

a p ointer to a base object

 This is called \using inheritance for reuse"

{ On the other hand, a consumer/Has-A relation

might be more appropriate:::  i.e., a pseudo-Has-A relation

42 41

Public Derivation

Private vs Public vs Protected

Derivation

 e.g.,

class A f

 Access control sp eci ers i.e., public, pri-

public:

vate, protected are also meaningful in

protected:

the context of inheritance

private:

 In the following examples:

g;

{ <:::.> represents actual omitted co de

class B : public A f

public:

{ [:::.] is implicit

[public A]

protected:

[protected A]

 Note, all the examples work for b oth data

private:

memb ers and metho ds

g;

43 44

Protected Derivation Private Derivation

 e.g.,  e.g.,

class A f class A f

public: public:

protected: private:

private: protected:

g; g;

class B : protected A f class B : private A f // also class B : A

public: public:

protected: protected:

[protected A]

[public A] private:

[public A]

private: [protected A]

g; g;

46 45

Summary of Access Rights

Other Uses of Access Control

 The following table describ es the access

rights of inherited metho ds

Sp eci ers

{ The vertical axis represents the access rights

of the metho ds of base class

 Selectively rede ne visibility of individual

metho ds from base classes that are de-

rived privately

{ The horizontal access represents the mo de of

inheritance

class A f

INHERITANCE

public:

ACCESS

+------+-----+-----+-----+

int f ;

M A | public | pub | pro | pri |

int g ;

E C +------+-----+-----+-----+

:::

M C | protected | pro | pro | pri |

B E +------+-----+-----+-----+

private:

E S | private | n/a | n/a | n/a |

int p ;

R S +------+-----+-----+-----+

g;

p p p

u r

b o i

class B : private A f

l t v

public:

A::f; // Make public

protected:

A::g ; // Make protected

 Note that the resulting access is always

g;

the most restrictive of the two

47 48

Common Errors with Access

Control Sp eci ers

General Rules for Access Control

 It is an error to \increase" the access of

Sp eci ers

an inherited metho d in a derived class

{ e.g., you may not say:

 Private metho ds of the base class are not

class B : private A f

accessible to a derived class unless the

// nor protected nor public!

public:

derived class is a friend of the base class

; // ERROR! A::p

g;

 If the sub class is derived publically then:

 It is also an error to derive publically and

1. Public metho ds of the base class are accessible

then try to selectively decrease the visibil-

to the derived class

ity of base class metho ds in the derived

class

2. Protected metho ds of the base class are acces-

{ e.g., you may not say:

sible to derived classes and friends only

class B : public A f

private:

A::f; // ERROR!

g;

50 49

Caveats

 Using protected metho ds weakens the data

hiding mechanism since changes to the

Overview of Multiple Inheritance

base class implementation might a ect all

derived classes. e.g.,

in C++

class Vector f

public:

 C++ allows multiple inheritance

//:::

protected:

// allow derived classes direct access

{ i.e., a class can be simultaneously derived from

T *buf ;

two or more base classes

t size ; size

g;

{ e.g.,

class Ada Vector : public Vector f

public:

t i f T &op erator[] size

class X f /* :::. */ g;

return this->buf [i];

class Y : public X f /* :::. */ g;

g

class Z : public X f /* :::. */ g;

// Note the strong dep endency on the name buf

class YZ : public Y, public Z f /* :::. */ g;

g;

{ Derived classes Y, Z, and YZ inherit the data

memb ers and metho ds from their resp ective

 However, p erformance and design reasons

base classes

may dictate use of the protected access

control sp eci er

{ Note, inline functions often reduces the need

for these eciency hacks:::

52 51

Liabilities of Multiple Inheritance

Multiple Inheritance Illustrated

 A base class may legally app ear only once

in a derivation list, e.g.,

Base

class Two Vector : public Vector, public Vec-

NON-VIRTUAL Base {

r // ERROR!

INHERITANCE to

 However, a base class may app ear multiple

within a derivation hierarchy Derived times

Derived Derived

e.g., class YZ contains two instances of class 1 2 {

12 X

 This leads to two problems with multiple

Base inheritance:

1. It gives rise to a form of metho d and data

ambiguity v memb er

v VIRTUAL

{ Explicitly quali ed names and additional meth-

are used to resolve this

INHERITANCE ods

It also may cause unnecessary duplication of

Derived Derived 2. rage 1 Derived sto

12 2

{ \Virtual base classes" are used to resolve

this

54 53

Overview of Virtual Base Classes

 Virtual base classes allow class designers

to sp ecify that a base class will be shared

Motivation for Virtual Base

among derived classes

Classes

{ No matter how often a virtual base class may

o ccur in a derivation hierarchy, only \one" shared

instance is generated when an object is instan-

tiated

 Consider a user who wants an Init Checked Vector:

 Under the hood, p ointers are used in derived

class Checked Vector : public virtual Vector

classes that contain virtual base classes

f /* :::. */ g;

class Init Vector : public virtual Vector

f /* :::. */ g;

 Understanding and using virtual base classes

class Init Checked Vector :

correctly is a non-trivial task since you

public Checked Vector, public Init Vector

must plan in advance

f /* :::. */ g;

{ Also, you must be aware when initializing sub-

classes objects:: :

 In this example, the virtual keyword, when

applied to a base class, causes Init Checked Vector

 However, virtual base classes are used to

to get one Vector base class instead of two

implement the client and server side of

many implementations of CORBA distributed

objects

55 56

Virtual Base Classes Illustrated

Vector

Virtual Base Classes NON-VIRTUAL Vector Initializing

INHERITANCE

 With C++ you must chose one of two

metho ds to make constructors work cor-

rectly for virtual base classes:

Checked Init Checked

You need to either supply a constructor in a

Vector Checked Vector 1.

base class that takes no arguments or

Vector virtual

has default arguments, e.g.,

Vector::Vector size t size = 100; // has problems:::

Or, you must make sure the most derived class

Vector 2.

calls the constructor for the virtual base class

its base initialization section, e.g., v in

v VIRTUAL

Init Checked Vector size t size, const T &init:

Vector size, ector size, Check

INHERITANCE V

Init Vector size, init Checked Init Checked Vector Checked Vector

Vector

57 58

Vector Interface Revised

Init Vector Interface

 The following example illustrates templates,

multiple inheritance, and virtual base classes

 A simple extension to the Vector base class,

in C++

that enables automagical vector initializa-

tion

include

include

template

// A simple-minded Vector base class,

class Init Vector : public virtual Vector

// no range checking, no initialization.

f

template

public:

class Vector

Init Vector size t size, const T &init

f

: Vector size

public:

f

Vector size t s: size s, buf new T[s] fg

for size t i = 0; i < this->size ; i++

T &op erator[] size t i f return this->buf [i]; g

*this[i] = init;

size t size void const f return this->size ; g

g

private:

// Inherits subscripting op erator and size.

size t size ;

g;

T *buf ;

g;

60 59

Init Checked Vector Interface and

Driver

Checked Vector Interface

 A simple multiple inheritance example that

 A simple extension to the Vector base class

provides for b oth an initialized and range

that provides range checked subscripting

checked Vector

template

template

class Init Checked Vector :

class Checked Vector : public virtual Vector

public Checked Vector, public Init Vector f

public:

f

Init Checked Vector size t size, const T &init:

public:

Vector size,

Init Vector size, init,

Checked Vector size t size: Vector size fg

Vector size fg Checked

T &op erator[] size t i throw RANGE ERROR f

// Inherits Checked Vector::op erator[]

g;

range i if this->in

return *inherited * this[i];

 Driver program

ERROR i; else throw RANGE

g

int main int argc, char *argv[] f

// Inherits inherited::size.

try f

size t size = ::atoi argv[1];

private:

t init = ::atoi argv[2]; size

typ edef Vector inherited;

Init Checked Vector v size, init;

cout << "vector size = " << v.size 

<< ", vector contents = ";

range size t i const f bool in

for size t i = 0; i < v.size ; i++

return i < this->size ;

cout << v[i];

g

g;

cout << "\n" << ++v[v.size  1] << "\n";

catch RANGE ERROR

f /* :::*/ g

g

61 62

Multiple Inheritance Ambiguity

Summary

 Consider the following:

 Inheritance supp orts evolutionary, incre-

struct Base 1 f int fo o void; /* :::. */ g;

mental development of reusable comp o-

struct Base 2 f int fo o void; /* :::. */ g;

nents by sp ecializing and/or extending a

struct Derived : Base 1, Base 2 f /* :::. */ g;

int main void f

general interface/implementation

Derived d;

d.fo o ; // Error, ambiguous call to fo o 

g

 Inheritance adds a new dimension to data

abstraction, e.g.,

 There are two ways to x this problem:

{ Classes ADTs supp ort the expression of com-

1. Explicitly qualify the call, by pre xing it with

monality where the general asp ects of an ap-

the name of the intended base class using the

plication are encapsulated in a few base classes

scop e resolution op erator, e.g.,

{ Inheritance supp orts the development of the

d.Base 1::fo o ; // or d.Base 2::fo o 

application by extension and sp ecialization with-

2. Add a new metho d fo o to class Derived similar

out a ecting existing co de:: :

to Ei el's renaming concept e.g.,

struct Derived : Base 1, Base 2 f

int fo o void f

 Without browser supp ort, navigating through

Base 1::fo o ; // either, b oth

Base 2::fo o ; // or neither

complex inheritance hierarchies is dicult:::

g

g;

64 63