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 Multiple Inheritance 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"
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 interface
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 \tree"
INHERITANCE Derived
{ SI requires a small amount of run-time over-
when used with dynamic binding head Derived TREE 4
3
{ e.g., Smalltalk, Simula, Object Pascal
2. Multiple Inheritance MI
More than one parent per derived class { Base Base 1
Derived 2
{ Forms an inheritance \Directed Acyclic Graph"
AG
D 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
of typ e T
template
Vector
e.g., /* File Vector.h incomplete wrt ini-
tialization and assignment */
t template
Vector
// Bare-b ones implementation, fast but not safe
template
template
class Vector f
t i f return this->buf [i]; g Vector
public:
Vector size t s;
int main void f
~Vector void;
Vector
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
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
shared
g;
27 28
Implementation of
Checked Vector
Checked Vector Use-case
e.g.,
e.g.,
template
include "Checked Vector.h"
Checked Vector
return i < this->size ;
typ edef Checked Vector
g
int fo o int size
template
f
Checked Vector
try
: inherited s fg
f
INT cv size; CV
template
int i = cv[cv.size ]; // Error detected!
Vector
// 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
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
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
t lower = ::atoi argv[1]; size
bnd lo fg : inherited hi lo + 1, lo
size t upp er = ::atoi argv[2];
Ada Vector
template
Ada Vector
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
ada vec i = ada vec i 1 + 1;
// or Vector
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
: 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:
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 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
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:
f
Init Checked Vector size t size, const T &init:
public:
Vector
Init Vector
Checked Vector size t size: Vector
Vector
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
Init Checked Vector
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