Multiple Inheritance in C++

19
CS 3370

description

CS 3370. Multiple Inheritance in C++. Multiple Base Classes. C++ allows multiple implementation inheritance Handy for multiple “is-a” situations Handy for reusing implementation without “is-a” Leads to C++’s Darkest Corner (IMHO) Inheritance “hierarchy” becomes a DAG Ambiguities galore! - PowerPoint PPT Presentation

Transcript of Multiple Inheritance in C++

Page 1: Multiple Inheritance in C++

CS 3370

Page 2: Multiple Inheritance in C++

C++ allows multiple implementation inheritance Handy for multiple “is-a” situations Handy for reusing implementation without

“is-a” Leads to C++’s Darkest Corner (IMHO)

Inheritance “hierarchy” becomes a DAG Ambiguities galore! Complicated rules

Page 3: Multiple Inheritance in C++

Invented with Common Lisp (“Flavors”) Clients inherit implementation to gain a

capability Printable, Storable, etc.

Mixin classes are often abstract Provides most but not all of feature You override virtual function(s) to complete the

feature A Mixin that itself happens to derive from another

class should do so via virtual inheritance (described later)

See AbleTest.cpp

Page 4: Multiple Inheritance in C++

Suppose we have the proverbial Shape hierarchy Circle, Triangle, etc.

If there is common code to all shapes, you can put it in Shape

If it is common to only some, keep it a secret Don’t have it derive from Shape

See next slide…

Page 5: Multiple Inheritance in C++

class Shape {…};class Common {…};class Logo : public Shape {…};class Circle : public Shape, protected Common {…};class Triangle: public Shape, protected Common {…};

Page 6: Multiple Inheritance in C++

A derived object has a subobject for each base class data duplication!

Name clashes possiblePossible duplicate data via

“diamond” inheritanceExamples: upcast.cpp, delta.cpp,

ambiguous.cpp

Page 7: Multiple Inheritance in C++

Base1

Base2

Base1

Base3

Derived

Page 8: Multiple Inheritance in C++
Page 9: Multiple Inheritance in C++

The derived class holds a pointer to the base subobject It is not inherited by value Only one subobject exists in the

complete objectTherefore, there is no ambiguity in

casting to the top-level class

Page 10: Multiple Inheritance in C++

Base2

Base1

Base3

Derived

Page 11: Multiple Inheritance in C++

There must be no ambiguity in name lookup

If multiple base classes contain the same member names, you have a problem If a member function, you can override it and

do the Right Thing If a data member, you must use “::”

And they must still be accessible Examples: ambiguous2.cpp,

disambiguate.cpp

Page 12: Multiple Inheritance in C++

A fancy name for the way virtual functions work The “most-derived” binding applies B::f dominates A::f if A is a (direct or

indirect) base class of BNon-virtual functions work the same

way for consistency

Page 13: Multiple Inheritance in C++

What if a D object calls f( ) via a pointer?

A { f }

B { f }

C

D

Page 14: Multiple Inheritance in C++

How do you initialize a virtual base?With diamond inheritance, there are

multiple paths to the shared baseWhich intermediate class is

responsible?

Page 15: Multiple Inheritance in C++

None! There’s no criterion for choosing

It is always initialized, therefore, by the most derived class Other initializations are ignored, but must

be supplied by every derived concrete class

This makes for weird, but necessary code

See next slides

Page 16: Multiple Inheritance in C++

Top

Left Right

Bottom

Page 17: Multiple Inheritance in C++

All virtual bases are initialized before non-virtual bases No matter where they are In top-down-left-to-right order

Subobjects are never initialized twice So the compiler has a lot of work to do

to keep track of things

Page 18: Multiple Inheritance in C++

A B C D

E F

G

virtual virtual

virtual virtual

What is the order of initialization for G g; ?(See virtinit2.cpp)

Page 19: Multiple Inheritance in C++

Affects copy constructors and assignment operators

Copy constructors work okay Most-derived class must still take care of virtual

base, similar to initialization example Assignment operators are different!

They are not inherited You must control all sub-assignments explicitly!

Examples: assignment.cpp, virtassign*.cpp