I've set up the classes so that the inheritance goes parent > child > grandchild.
The problem is that when the child inherits using virtual, and the grandchild tries to call the child's constructor, the child's constructor doesn't call the correct parent constructor. It calls the default parent constructor instead.
Below, the output should be 123, but is 023 when the child inherits with the virtual keyword. For the sake of the question, let's just say that the code I'm working with requires that child inherits from the parent virtually.
Is there a way to force the child constructor to call the non-default parent constructor? If not, just an explanation as to why it's behaving like this would be much appreciated. I might be fundamentally misunderstanding virtual. I know it's effects, but not what it's fundamentally doing.
An interesting note is that if the parent pointer "test" points to a child with the correct number of parameters rather than a grandchild, the child calls the correct parent constructor regardless of virtual. Anyone know?
Virtual parents must be constructed before non-virtual parents. The reason for that is because it's possible for the virtual parent to be called more than once. For example:
class Top
{
public:
Top(); // ctor A
Top(int); // ctor B
Top(int,int); // ctor C
};
class Mid1 : virtualpublic Top
{
public:
Mid1() : Top(1) { } // calls ctor B
};
class Mid2 : virtualpublic Top
{
public:
Mid2() : Top(1,2) { } // calls ctor C
};
class Lowest : public Mid1, public Mid2
{
// calls ctor A by default (see below)
};
Note Lowest is going to call both Mid1 and Mid2's constructor. But each of those constructors call a different Top constructor. So which one is the compiler supposed to use? It obviously can't construct Top twice!
Therefore the solution here is to have Lowest call Top's ctor directly, rather than through Mid1, Mid2:
1 2 3 4 5
class Lowest : public Mid1, public Mid2
{
public:
Lowest() : Top(3,4) { } // now it calls ctor C instead of ctor A
};
In your case... grandchild is not calling any ctor for the virtual parent, therefore the default ctor is assumed.