In this episode, we will discuss the most subtle point of multiple inheritance. This is the reason why some languages refuse to include multiple inheritance. This is what we call virtual classes. Let us begin by illustrating the problem, to which this new concept pertains. Let us go back to our infamous example regarding ovoviviparous - they are oviparous and viviparous. This is a case of multiple inheritance since the class "Ovovivipare" inherits from the classes "Vivipare" and "Ovipare". Now, let us imagine that Ovipare inherit from the class "Animal" (indeed, an oviparous is an animal), Similarly, a viviparous is also an animal. Therefore, in a certain way, an ovoviviparous is two times an animal. Here is a more technical example from the system library of C++. Of couse, you do not have to comprehend every single detail; we merely wish to make it obvious that the problems we are talking about occur in daily life. So, regarding the "iostream" class (we have talked about it along with "cout"), it so happens that this "iostream" class is both an "ostream" and an "istream". Then, the conceptors of these classes have decided that both "istream" and "ostream" were also "ios" (no matter what it actually is). Consequently, "iostream" is apparently two times an "ios". By the way, this how, in reality, we represent multiple inheritance diagrams. We never draw the same class multiple times on an inheritance diagram. However, we draw it once only with both inheritances going back to the same class. The reason why we have drawn our diagram this way is so that you understand what the problem is. What does it mean that an ovoviviparous is an oviparous (which is an animal) and also a viviparous (which is an animal too) ? Does it mean that an ovoviviparous is two times an animal? For example, if an animal has a head, does an ovoviviparous have two? Does it have an oviparous head and a viviparous head? Or does it only have one head? Is it the very same animal? This here is the core problem. Due to this conundrum, certain languages refuse to provide multiple inheritance. In C++, if we do not take precautions (this is why we drew our diagram in such an unusual way), our ovoviviparous will indeed inherit twice from the class "Animal". Each instance of Ovovivipare will have two times the attributes from the class "Animal". Let us see this in an concrete example. Let us imagine the following example. Here, we have written it in a condensed way so that it can fit in a single slide. We thus have the class "Animal". It has a constructor which initializes its attribute. This attribute is a character string indicating what kind of head the animal has. We receive a character string and we initialize the head attribute with the received paramater. Then, we have an "Ovipare" class, which inherits from the class "Animal". This "Ovipare" class redefines a default constructor here - we kept things really simple here. This default constructor calls the constructor of "Animal" passing a character string : "à cornes" (TN: means "horny"). This means that an instance of Ovipare have a horny head. Then, we have the class "Vivipare" which also inherits from "Animal". It also has a default constructor which says that the animal has, for example, a fish head. Finally, the class "Ovovivipare" inherits from "Ovipare" and from "Vivipare". We thus get the very diagram that we have presented previously. Then, we have a public method called "affiche" (TN : means "print") which prints the head inherited from "Animal" through "Ovipare". Here, we can see the scope resolution operator. We do have an ambiguity since Ovovivipare inherits two heads; one from "Ovipare", the other from "Vivipare". In order to solve the ambiguity, we use, as always, the scope resolution operator. Thus we say "j'ai une tête" (TN: means "I have a head"), print the head of Ovipare, "et une tête" (TN: means "and a head"), and print the head of Vivipare. Now if, for example, in the main function or elsewhere, we declare an Ovovivipare "x" - it is absolutely possible since "Ovovivipare" has a default constructor. Now, " x " will be constructed through the default constructor. It will call the two default constructors of the super-classes in the inheritance declaration oder, here at the class level. Here, we will thus call the constructors of "Ovipare" and of "Vivipare". We can very well do this default construction here. Then, if we print " x ", we will have the following printing for this ovoviviparous : "j'ai une tête à corne" (TN: means "I have a horny head"), which is the result of the initialization through the default constructor of "Ovipare", and "et une tête de poisson" (TN: means "and a fish head"), which is the result of the printing of "Vivipare::tete" initialized through the default constructor of the class "Vivipare". Thus, the class "Ovovivipare" has indeed inherited two heads. There are two animals in the class "Ovoviviparous". Here, of course, it is rather unwanted for an ovoviviparous to retrieve two heads through this multiple inheritance. Same for the fact that there are two copies of "Animal". Please note that, in certain cases, we may to effectively inherit the attributes twice. For example, let us imagine that we have a hierarchy of vehicles. We have petrol engine vehicles, and electric vehicles. Now, we imagine that we have hybrid vehicles: they are petrol engine vehicles and electric vehicles. The question is : Is a hybrid vehicle a single vehicle, just as was the case for ovoviviparous? Or are they indeed two vehicles? This depends on what we mean by "vehicle"? If, by vehicle, we mean four tires, a steering wheel... then, naturally, a hybrid vehicle has only one time four tires and a steering wheel and surely not eight tires and two steering wheels. If, on the other hand, we mean that a vehicle has an engine, it is different. Indeed, we have an electric engine and a petrol engine. In this case, we will wish to have two engines in "hybride". Now, you can see that this is a subtle problem which is very conception-dependant. We need to understand what the inheritance relationship truly means in the case at hand. If we do not wish to receive several times the attributes of the super-super-class, we will need to do something particular in order to prevent it : we will declare the inheritance link as a virtual link. We are once again using the keyword "virtual" here, but for another reason. Here, the inheritance link is virtual. Thus, if a super-class has its inheritance links towards its sub-classes declared as virtual, the super-class will be called a virtual super-class. Be careful, this has nothing to do with an abstract class! In an abstract class, we have virtual methods, and, in a virtual class, we can whatever method we desire. It is the sub-classes' inheritance link that is special, that is virtual. Do not confuse one concept with the other. The general syntax is as follows : for the sub-classes we will say that we inherit virtually. Personally, we say that it is a virtual inheritance rather than a virtual class. Thus, we say that inherit virtually from the super-class. Concretely, in our ovoviviparous example, we will change things at the level of Ovipare and Vivipare. This way, Ovipare inherits virtually from the class "Animal" : consequently, "Animal" is a virtual class. Similarly, we will write that "Vivipare" inherits virtually from the class "Animal". Please note that it is the class we inherit from several times that is called virtual. Here, this means that it is the class "Animal" that will be a virtual class. We have to modify the inheritance links from Ovipare towards "Animal" and from "Vivipare" towards "Animal" even though it is the class "Ovovivipare" that introduces the problem. You can see that there is a problem with the general conception. The designers of the classes "Ovipare" and "Vivipare" must declare a virtual inheritance towards the class "Animal" because, possibly, someone, someday, will imagine a sub-class "Ovovivipare", which inherits from "Ovipare", and from "Vivipare". This is a severe flaw of virtial inheritance and virtual classes. It creates a dependency of higher-level inheritances towards possible lower-level inheritances. This is another reason why certain programming languages want nothing to do with virtual inheritance. However, since the possibility exists in C++, we should use it carefully, and parcimoniously. Now let us go back to our multiple inheritance diagrams. In order to signify that the inhertiance links are virtual, we will use dash lines instead of the full ones. Now, let us see concretely what happens with virtual inheritances. What happens in our example if we render these two inheritances virtual? The "Ovovivipare" class will only have one single head. What will happen is that we will only create one "Animal" in "Ovovivipare". We will no longer create two animals inside "Ovovivipare". This solves the aforementioned problem. Now let us see how virtual classes, virtual inheritances, impact the constructors. It generates a strong restraint for the programmer. But first, a remainder. Remember that, in a usual inheritance, the constructor of the sub-class calls the constructor (or the constructors in the case of multiple inheritance) of the direct super-classes. Direct meaning that they inherit directly from these super-classes. So, in the case of multiple inheritance with a virtual super-super-super class, the responsability to initialize, to call the constructors of this virtual super-super-class belongs to all the sub-classes we want to create an instance of. Thus, all these sub-classes, sub-sub-classes... which inherit indirectly from a virtual super-super-super-class, and are not abstract (which means we can create instances of them), will have to explicitly call the constructor of the virtual super-super-super-class. As you can plainly see, this is a strong constraint in the declaration of the constructor of the sub-classes. Let us see this concretely on the Ovovivipare example. In this case, we have the sub-sub-class "Ovovivipare", which inherits from the sub-classes "Ovipare" and "Vivipare". These two classes inherit virtually from the class "Animal". We thus have a virtual class "Animal". Consequently, the sub-class "Ovovipare" must, in its constructors, directly call the constructor of "Animal". We will thus have to write the following instruction in the constructor of Ovovivipare : an explicit call to the constructor of "Animal" is mandatory here. Let us suppose this constructor takes three parameters before we write the call to the usual constructor of Ovovivipare's direct super-classes. As we have said, this is a strong constraint regarding virtual classes. Now, let us see what concretely happens when we declare an instance. Let us declare an instance " o " of Ovovivipare. Thus we are calling Ovovivipare's constructor. First of all, we will trigger the constructor of an "Animal". Thus, when we are building a sub-sub-class, which inherits from a virtual class, the first thing we do is to create the virtual class. There is only one virtual class. Indeed, the goal of multiple inheritance and of virtual classes is to have only one virtual classes and not several along with all the inheritance paths. Since we have only one virtual class, we must build it first and foremost. Consequently, we will build this "Animal" first. The first constructor to be called is the constructor of "Animal". Then, we will go back to the normal calls of the constructors. Thus, the constructor of Ovovivipare will then call the constructor of Ovipare. This constructor of "Ovipare" should normally call the constructor of the super-class. But here, since we have already initialized the super-class, this call to the constructor of "Animal" found in the constructor of "Ovipare", will be ignored. Similarly, we will then call the constructor of "Vivipare", which will ignore the call to the constructor of "Animal" since it has already been done. Let us now sum up the construction of an Ovovivipare. First of all, we call the constructor of "Animal". Secondly, we call the constructor of "Ovipare", in which we ignore the supplementary call to the constructor of "Animal". Thirdly, we call the constructor of "Vivipare", in which we ignore the supplementary call to the constructor of "Animal". Finally, we conclude by the usual initialization of its own attributes. Let us sum one final time. During the creation of an object of the most derived class, the sub-sub-sub-class of a virtual class, it is the constructor of this sub-sub-sub-class that is tasked with the direct call to the constructor of the virtual super-class. Also, the calls to the constructor of the virtual super-class in the intermediate classes are simply ignored. Naturally, if the virtual super-class has a default constructor, it is not mandatory to explicitly call its constructor. But, one way or the other, there will be a call to this default constructor : it will be called during the creation of the most derived instance. As usual, if we omit the call to the constructor of the virtual super-super-class in the sub-sub-classes and that this virtual super-super-class has not default constructor, the compiler will naturally report an error. Indeed, it will try to call a non-existing constructor. So, in a class hieararchy, where there are virtual super-classes, the initialization of the virtual super-classes must be done by all the sub-classes we wish to create. The constructor of the virtual super-classes will be called first and foremost. Then, the calls to the virtual super-classes in the intermediate classes will be ignored. Regarding non-virtual super-classes, they are then initialized in the order of the inheritance declaration, as usual. The call order of the copy constructors follows this rule aswell. As always, the call order of the destructors is the reverse order to the constructors'. Thus concludes this sequences on this slightly delicate subject of virtual classes, and virtual inheritance.