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:
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()