virtual inheritance not working with non-default constructors *SOLVED*

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <iostream>

using namespace std;

class parent
{
	private:
		int a;
	public:
		parent()
		{
			a = 0;
		}
		parent(int tempA)
		{
			a = tempA;
		}
		virtual ~parent()
		{

		}

		void outA() {
			cout << a;
		}
		virtual void outputAll() = 0;
};

class child : virtual public parent
{
	private:
		int b;
	public:
		child()
		{
			b = 0;
		}
		child(int tempA, int tempB) : parent(tempA)
		{
			b = tempB;
		}
		virtual ~child()
		{

		}

		void outB() {
			cout << b;
		}
		void outputAll()
		{
			outA();
			outB();
		}
};

class grandchild : public child
{
	private:
		int c;
	public:
		grandchild()
		{
			c = 0;
		}
		grandchild(int tempA, int tempB, int tempC) : child(tempA, tempB)
		{
			c = tempC;
		}
		virtual ~grandchild()
		{

		}

		void outC() {
			cout << c;
		}

		void outputAll()
		{
			outA();
			outB();
			outC();
		}
};

int main()
{

	parent* test = new grandchild(1,2,3);
	test->outputAll();
	delete test;

	return 0;
}


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?
Last edited on
The virtual class constructor is called the first. So you should rewrite the constructor

grandchild(int tempA, int tempB, int tempC) : child(tempA, tempB)

something as

grandchild(int tempA, int tempB, int tempC) : parent( tempc/* or another parameter*/ ), child(tempA, tempB)
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Top
{
public:
  Top(); // ctor A
  Top(int); // ctor B
  Top(int,int);  // ctor C
};

class Mid1 : virtual public Top
{
public:
  Mid1() : Top(1) { }  // calls ctor B
};

class Mid2 : virtual public 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.

EDIT: dammit vlad! you ninja ;)
Last edited on
You guys are awesome. Worked perfectly, thanks.
Topic archived. No new replies allowed.