Virtual Inheritance

Lets say I have this code:

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
#include <iostream>
using namespace std;
 
class Animal
{
public:
    Animal()
    {
        cout << "Creating Animal\n";
    }
};
 
///////////////////////////
 
class FourLegs : public Animal
{
public:
    FourLegs()
    {
        cout << "Creating FourLegs\n";
    }
};
 
///////////////////////////
 
class Mammal : virtual public Animal
{
public:
    Mammal()
    {
        cout << "Creating Mammal\n";
    }
};
 
///////////////////////////
 
class Fox : public FourLegs, public Mammal
{
public:
    Fox()
    {
        cout << "Creating Fox\n";
    }
};
 
int main()
{
        Fox myfox;
        return 0;
}


The output of this program is as follows:


Creating Animal
Creating Animal
Creating FourLegs
Creating Mammal
Creating Fox


I do not understand how this output came to be. Does anybody understand the construction of inheritance trees that involve virtual base classes?
What is confusing you? The output looks OK to me, so I don't really know where to start to explain. See http://en.wikipedia.org/wiki/Virtual_inheritance for details. Perhaps you were expecting a single Animal? If that's the case, you need to use virtual inheritance on both bases.
I was just wondering how two Animal instances came in a row. How does having a class inherit virtually make it different then if it were to inherit normally?
closed account (zb0S216C)
I already answered this in your last thread.

Flurite wrote:
class Mammal : virtual public Animal

Here, virtual has no effect. In this context, virtual simply means if B virtually inherits from A, and C inherits from B, A will become the base-class of C.

FourLegs and Mammal both have an Animal base-class. Therefore, 2 Animals are constructed. Since Fox inherits neither FourLegs nor Mammal virtually, Fox will inherit the Animal base-class of FourLegs and Mammal, hence the multiple Animal construction.

However, if your virtually inherited both FourLegs and Mammal, the compiler will eliminate one of the Animal base-classes; thus eliminating an Animal construction.

Wazzak
Framework, it sounds like you're saying that to construct one animal Flurite needs to do this:
 
class Fox: virtual public Mammal, virtual public FourLegs

This will actually create 2 animals again, but in this case Mammal and it's base animal will both be created before the animal of FourLegs is created.
In order to create a single Animal base, make both Mammal and FourLegs virtually inherit Animal:
1
2
3
class Mammal: virtual public Animal
//AND
class FourLegs: virtual public Animal


EDIT: I think I got what you mean Flurite.
You're wondering why you get:
Animal
Animal
etc..

And not:

Animal
Mammal
Animal
FourLegs

?
This is because the base classes for any virtually inherited bases need to be constructed before anything else to ensure that only one base is shared among all classes which do virtually inherit it. So "Mammal's" Animal needs to be constructed before anything else, since it will be shared between all classes which virtually inherit from it.
Last edited on
closed account (zb0S216C)
@BlackSheep: You're right - Virtual inheritance isn't a strong suit of mine.

Wazzak
@Framework,

I think the virtual changes the result one way or another as shown by the output. Maybe a walk-through of what the compiler is doing would be helpful.

Also, does A really become a base class of C if B is virtually inherited from A?
The virtual inheritance may help to solve diamond problem, but not all other problems that you may get when using multi-inheritance.
@BlackSheep,

Yes, that is exactly my problem and your answer sounds correct. Is this the correct walk-through the compiler is going through?

1. The compiler begins to construct Fox. It goes through the inheritance tree and sees a virtual base class Animal and constructs it.

2. After constructing Animal, it goes to Fox's base-specfier list and begins construction of FourLegs. When it goes to FourLegs, it sees that it must create another Animal class and this creates one. Then, it creates FourLegs.

3. The compiler then goes back to Fox and goes to the next class in the base-specifier list, Mammal. It sees that it inherited virtually from Animal, knows it already created the virtual base class, so it goes ahead and creates Mammal.

4. It is done with all the base classes and thus creates Fox.
Last edited on
Yeah. You can even try switching the order of the inheritance list around:
 
class Fox : public Mammal, public FourLegs

Now you'll print:

animal
mammal
animal
fourlegs

since Mammal comes first in the list.
Hmm.. making the virtual base class first seems to be very logical now, because that ensures that there is only one version of it.

All makes sense now, thanks everyone.
Last edited on
What do you mean it ensures there is only one version? FourLegs will always have its own version of Animal, since it didn't inherit it virtually. Mammal will always use the "shared" Animal class, since that's what you told the compiler.
I meant that if FourLegs and Mammal inherited Animal virtually, creating the virtual base class first would create that "shared" class with limited problems.
Oh, okay! Sorry, I thought you were talking about the code I posted (Changing position of Mammal and FourLegs in list).
Topic archived. No new replies allowed.