multiple inheritance in c++
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 PresentationTRANSCRIPT
CS 3370
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
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
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…
class Shape {…};class Common {…};class Logo : public Shape {…};class Circle : public Shape, protected Common {…};class Triangle: public Shape, protected Common {…};
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
Base1
Base2
Base1
Base3
Derived
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
Base2
Base1
Base3
Derived
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
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
What if a D object calls f( ) via a pointer?
A { f }
B { f }
C
D
How do you initialize a virtual base?With diamond inheritance, there are
multiple paths to the shared baseWhich intermediate class is
responsible?
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
Top
Left Right
Bottom
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
A B C D
E F
G
virtual virtual
virtual virtual
What is the order of initialization for G g; ?(See virtinit2.cpp)
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