Professional Documents
Culture Documents
Search
Starting out
Get the Ebook
Get Started with C or C++
Getting a Compiler
Book Recommendations
Tutorials
C Tutorial
C++ Tutorial
Java Tutorial
Game Programming
Graphics Programming
Algorithms & Data Structures
Debugging
All Tutorials
Practice
Practice Problems
Quizzes
Resources
Source Code
Source Code Snippets
C and C++ Tips
Finding a Job
References
Function Reference
Syntax Reference
Programming FAQ
Getting Help
Message Board
Email
About Us
By Andrei Milea
Multiple inheritance in C++ is a powerful, but tricky tool, that often leads to
problems if not used carefully. This article will teach you how to use virtual
inheritance to solve some of these common problems programmers run into. If you're
not familiar with multiple inheritance, check out this article on multiple
inheritance.
To understand how this is works, let's take a look at how the objects are
represented in memory. Inheritance simply puts the implementation of two objects
one after another, but in this case radio is both a transmitter and a receiver, so
the storable class gets duplicated inside the radio object. The g++ compiler will
complain when compiling the code: error: 'request for member "write" is ambiguous',
because it can't figure out whether to call the method write() from
storable::receiver::radio or from storable::transmitter::radio.
In order to keep track of the single instance of the storable object, the compiler
will provide a virtual function table (vtable) for classes transmitter and
receiver. When a radio object is constructed, it creates one storable instance, a
transmitter instance and a receiver instance. The transmitter and receiver classes
have a virtual pointer in their vtables that stores the offset to the storable
class. When the transmitter class or the receiver class goes to access any fields
of the storable, it uses the virtual pointer in its vtable to find the storable
object and find the field in it. This tutorial offers a comprehensive explanation
of the memory layout of virtual inheritance in GCC.
Constructors and Virtual Inheritance
Because there is only a single instance of a virtual base class that is shared by
multiple classes that inherit from it, the constructor for a virtual base class is
not called by the class that inherits from it (which is how constructors are
called, when each class has its own copy of its parent class) since that would mean
the constructor would run multiple times. Instead, the constructor is called by the
constructor of the concrete class. In the example above, the class radio directly
calls the constructor for storable. If you need to pass any arguments to the
storable constructor, you would do so using an initialization list, as usual:
radio::radio ()
: storable( 10 ) // some value that storable needs
, transmitter()
, receiver()
{}
One thing to be aware of is that if either transmitter or receiver attempted to
invoke the storable constructor in their initialization lists, that call will be
completely skipped when constructing a radio object! Be careful, as this could
cause a subtle bug!
By the way, the constructors for virtual base classes are always called before the
constructors for non-virtual base classes. This ensures that a class inheriting
from a virtual base class can be sure the virtual base class is safe to use inside
the inheriting class's constructor.
The destructor order in a class hierarchy with a virtual base class follows the
same rules as the rest of C++: the destructors run in the opposite order of the
constructors. In other words, the virtual base class will be the last object
destroyed, because it is the first object that is fully constructed.
Delegating to a sister class
int main()
{
radio *rad = new radio();
receiver *r1 = rad;
transmitter *r2 =rad;
rad->write();
r1->write();
r2->write();
return 1;
}
Because of virtual inheritance, when the write() function from the transmitter
class is called, the method read() from the receiver class gets called (as you may
have noticed, the transmitter class doesn't have a read() function). In the above
hierarchy we can instantiate only the radio class because transmitter and receiver
are abstract due to virtual inheritance.
Other considerations when using multiple inheritance in C++
When you use a class that is based on virtual inheritance like radio, you should
avoid using C style casts and use the C++ specific dynamic_cast instead (more
information on casting). It will perform a runtime check for validity before
casting, so you can be sure that the type of the object you want to cast is related
(by inheritance) with the object type you want to cast into. If they are not
related, the result will be a NULL pointer or a bad_cast exception in case of
references.
Want to become a C++ programmer? The Cprogramming.com ebook, Jumping into C++,
will walk you through it, step-by-step. Get Jumping into C++ today!
Popular pages
Exactly how to get started with C++ (or C) today
C Tutorial
C++ Tutorial
5 ways you can learn to program faster
The 5 Most Common Problems New Programmers Face
How to set up a compiler
8 Common programming Mistakes
What is C++11?
How to make a game in 48 hours
Recent additions subscribe to a feed
How to create a shared library on Linux with GCC - December 30, 2011
Enum classes and nullptr in C++11 - November 27, 2011
Learn about The Hash Table - November 20, 2011
Rvalue References and Move Semantics in C++11 - November 13, 2011
C and C++ for Java Programmers - November 5, 2011
A Gentle Introduction to C++ IO Streams - October 10, 2011
Search
Google Custom Search
Join our mailing list to keep up with the latest news and updates about
Cprogramming.com!
Name
Submit Form
Subscriber Counter
Popular pages
C tutorial
C Tutorial
Get started
Exactly how to get started with C++ (or C) today
Learn to program
5 ways you can learn to program faster
C++ tutorial
C++ Tutorial
Problems new programmers face
The 5 Most Common Problems New Programmers Face
Learn to make a game
How to make a game in 48 hours
Common problems
8 Common Programming Mistakes
C++11
What is C++11?
Image credits