Diamond problem in inheritance is side-effect of multiple inheritance architecture where occurrence of double base component leads to duplication of data. This also leads to ambiguity while accessing base class members and data.
Empty Class
A typical diamond is created as shown:
#include<iostream> //main header
using namespace std; //namespace
class mytop
{
public:
mytop()
{
cout << "mytop()" << endl;
}
~mytop()
{
cout << "~mytop()" << endl;
}
};
class myleft : public mytop
{
public:
myleft()
{
cout << "myleft()" << endl;
}
~myleft()
{
cout << "~myleft()" << endl;
}
};
class myright : public mytop
{
public:
myright()
{
cout << "myright()" << endl;
}
~myright()
{
cout << "~myright()" << endl;
}
};
class mybottom : public myleft, public myright
{
public:
mybottom()
{
cout << "mybottom()" << endl;
}
~mybottom()
{
cout << "~mybottom()" << endl;
}
};
int main()
{
mybottom b;
return 0;
}
The output is:
mytop()
myleft()
mytop()
myright()
mybottom()
~mybottom() ~myright()
~mytop()
~myleft()
~mytop()
Clearly, the mytop( ) constructor is called 2 times, in in context of myleft( ) and one in myright( ).
Size of Objects: In above example, the impact on size of objects when content is added in diamond hierarchy
sizeof (mytop) = 1 //empty class
sizeof(myleft) = 1 //empty class inherits top
sizeof(myright) = 1 //empty class inherits top
sizeof(mybottom) = 2 //empty class with left &
//right (of size=1)
class with one integer data
In this hierarchy, if an integer variable is added in class mytop
class mytop
{
int ix; //integer of size 4 bytes
public:
mytop()
{
cout << "mytop()" << endl;
}
~mytop()
{
cout << "~mytop()" << endl;
}
};
Size of diamond object will be
sizeof (mytop) = 4 //equal to size of integer (=4)
sizeof(myleft) = 4 //empty class inherits top (of size 4)
sizeof(myright) = 4 //empty class inherits top (of size 4)
sizeof(mybottom) = 8 //empty class with left (of size 4) and
// right (of size 4) objects
Virtual base class for solving diamond problem in inheritance:
Since, the diamond hierarchy is duplicating the data of top class through left and right classes. Therefore, to resolve this, virtual base classes can be used.
Left and right classes will derive from mytop using virtual keyword.
class myleft : public virtual mytop
class myright : public virtual mytop
Now, the size of diamond object will be
sizeof (mytop) = 4 //equal to size of integer (size 4)
sizeof(myleft) = 16 //empty class inherits
//mytop with
//integer(size 4) and
//one virtual base ptr
//(of size 8)
//= total 12 bytes
//=> becomes 16
//(multiple of 8)
sizeof(myright) = 16 //same as myleft
sizeof(mybottom) = 24 //size of integer in mytop
//(size = 4)
// + size of virtual base ptr
//in myleft
// (size = 8)
// + size of virtual base ptr
//in myright
// (size = 8)
// total = 20 =>
//becomes 24 (multiple of 8)
The virtual base pointer will add to size overhead, however, if the saving is more then this overhead may be acceptable.