Multiple inheritance & virtual base classes

Share the Article

Multiple this pointers: In multiple inheritance object, the compiler includes top parent class part in object multiple times. Therefore, there will be more than one “this pointers” each representing its inclusion of parent. part. The virtual base class shall ultimately solve the problem.

Following example demonstrates different values of “this” pointer in different parts of multiple inheritance hierarchy

#include <iostream> //main header using namespace std; //namespace class top { public: void thisfunda() { cout << "top " << this << endl; } }; class leftBase : public top { public: void thisfunda() { top::thisfunda(); cout << "left " << this << endl; } }; class rightBase : public top { public: void thisfunda() { top::thisfunda(); cout << "right " << this << endl; } }; class bottom : public leftBase, public rightBase { public: void thisfunda() { leftBase::thisfunda(); rightBase::thisfunda(); cout << "bottom " << this << endl; } }; int main() { bottom b; b.thisfunda(); return 0; }

Output:

top 0x7ffc83d5e25e left 0x7ffc83d5e25e top 0x7ffc83d5e25f right 0x7ffc83d5e25f bottom 0x7ffc83d5e25e

Ambiguity to access common parent

In above example, since, the top part includes itself two times. This setup causes ambiguity while calling any function in parent part. Basically, an object cannot call functions in parent class without properly resolving reference. The C++ compiler will not understand that function should be called in context to which inclusion of parent part (left or right). It can call the function in parent using any of the 2 this pointers.

#include <iostream> //main header using namespace std; //namespace class top { public: void topfunc() { cout << "topfunc()" << endl; } }; class leftBase : public top { }; class rightBase : public top { }; class bottom : public leftBase, public rightBase { }; int main() { bottom b; b.topfunc(); //Ambiguous, occurs //2 this ptrs in object return 0; }

The output is:

ambiguous call for function in top class in diamond hierarchy

Two ways to resolve parent reference

Scope Resolution:

The first correct way is to use scope resolution operator for selecting appropriate parent class.

Example, the above calling code should be modified like this:

bottom b; b.topfunc(); //wrong way b.leftBase::topfunc(); //wright way b.rightBase::topfunc();//wright way

Virtual Base:

Second way to solve this multiple inheritance ambiguity problem is to use virtual base classes. This method ensures that the compiler include the top class only once in object. Additionally, there shall be virtual base pointers inside the objects, these shall help in referring to same common parent part. Hence, there will be some overhead in terms of space and time.

#include <iostream> //main header using namespace std; //namespace class top { public: void topfunc() { cout << "topfunc()" << endl; } }; class leftBase : public virtual top { }; class rightBase : public virtual top { }; class bottom : public leftBase, public rightBase { }; int main() { bottom b; b.topfunc(); //This will work now b.leftBase::topfunc(); b.rightBase::topfunc(); return 0; }

The output is:

topfunc() topfunc() topfunc()

Main Funda: By making base class virtual, compiler ensures that the top class is included only once in object

Related Topics:

Parametrized constructor
Virtual Destructor & Pure Virtual Destructor
Smart Pointers: unique_ptr<T>
Diamond problem – Overhead of virtual base
Multiple Inheritance has multiple this pointers
Understanding multiple inheritance & virtual base classes
Understanding the copy constructor
What is move constructor ?
Understanding the order of calling constructors and destructors
What is an explicit constructor ?
Smart Pointers: shared_ptr <T> 
What happens when exception thrown from a constructor?
Why a destructor should never throw exception?
Compiler Generated Destructor is always non-virtual
Which member functions are generated by compiler in class?
Understanding array version of new[] & delete[]

Share the Article

Leave a Reply

Your email address will not be published. Required fields are marked *