In this article
A class can be obtained from much more than one base class. In a multiple-inheritance model (where classes are acquired from more than one basic class), the basic classes room specified making use of the base-list grammar element. Because that example, the course declaration for CollectionOfBook, obtained from Collection and Book, deserve to be specified:
// deriv_MultipleBaseClasses.cpp// translate in with: /LDclass collection ;class book ;class CollectionOfBook : publicly Book, public arsenal // new members;The bespeak in which base classes room specified is not far-reaching except in specific cases wherein constructors and destructors space invoked. In this cases, the bespeak in which basic classes room specified influence the following:
The order in i m sorry initialization by constructor bring away place. If your code depends on the Book portion of CollectionOfBook to be initialized prior to the repertoire part, the bespeak of specification is significant. Initialization takes place in the order the classes room specified in the base-list.
You are watching: When more than one class is derived from a base class, the situation is called
The stimulate in which destructors space invoked come clean up. Again, if a specific "part" that the course must be existing when the other part is gift destroyed, the stimulate is significant. Destructors are dubbed in the reverse order that the classes stated in the base-list.
The bespeak of specification of base classes can impact the storage layout of the class. Execute not make any programming decisions based on the bespeak of base members in memory.
When clues the base-list, you can not specify the same course name much more than once. However, the is possible for a course to it is in an indirect base to a obtained class much more than once.
Virtual basic classes
Because a class can it is in an indirect base course to a derived class much more than once, C++ gives a method to optimize the way such basic classes work. Online base classes sell a means to save an are and prevent ambiguities in course hierarchies that use multiple inheritance.
Each nonvirtual object contains a copy the the data members characterized in the basic class. This duplication wastes an are and needs you come specify which copy of the base course members you desire whenever you accessibility them.
When a base class is stated as a digital base, it have the right to act as an indirect base much more than as soon as without duplication of its data members. A single copy of its data members is shared by every the base classes that usage it together a online base.
When heralding a virtual base class, the virtual keyword appears in the basic lists the the obtained classes.
Consider the class hierarchy in the following figure, i beg your pardon illustrates a simulated lunch line.
In the figure, Queue is the base class for both CashierQueue and also LunchQueue. However, when both classes are an unified to form LunchCashierQueue, the following difficulty arises: the new class has two subobjects of form Queue, one indigenous CashierQueue and also the other from LunchQueue. The following figure shows the theoretical memory layout (the actual memory layout might be optimized).
Note the there are two Queue subobjects in the LunchCashierQueue object. The following code declares Queue to be a digital base class:
// deriv_VirtualBaseClasses.cpp// compile with: /LDclass Queue ;class CashierQueue : online public Queue ;class LunchQueue : virtual public Queue ;class LunchCashierQueue : windy LunchQueue, public CashierQueue ;The virtual keyword ensures that just one copy that the subobject Queue is had (see the adhering to figure).
A class can have both a online component and also a nonvirtual component of a offered type. This happens in the conditions illustrated in the adhering to figure.
In the figure, CashierQueue and also LunchQueue usage Queue together a digital base class. However, TakeoutQueue states Queue together a basic class, no a digital base class. Therefore, LunchTakeoutCashierQueue has actually two subobjects of form Queue: one indigenous the inheritance course that includes LunchCashierQueue and also one from the course that contains TakeoutQueue. This is portrayed in the adhering to figure.
Virtual inheritance provides far-reaching size services when compared with nonvirtual inheritance. However, it can introduce extra processing overhead.
If a derived class overrides a virtual role that the inherits from a virtual base class, and also if a constructor or a destructor for the obtained base class calls that duty using a tip to the online base class, the compiler might introduce additional hidden "vtordisp" fields into the classes through virtual bases. The /vd0 compiler alternative suppresses the enhancement of the hidden vtordisp constructor/destructor displacement member. The /vd1 compiler option, the default, permits them wherein they space necessary. Rotate off vtordisps just if you space sure the all course constructors and destructors call virtual attributes virtually.
The /vd compiler choice affects whole compilation module. Use the vtordisp pragma come suppress and also then reenable vtordisp areas on a class-by-class basis:
#pragma vtordisp( off )class GetReal : virtual public ... ;\#pragma vtordisp( on )
Name ambiguitiesMultiple inheritance introduce the opportunity for name to it is in inherited along much more than one path. The class-member names follow me these courses are no necessarily unique. These name disputes are dubbed "ambiguities."
Any expression that describes a course member must make one unambiguous reference. The following example shows how ambiguities develop:
// deriv_NameAmbiguities.cpp// compile with: /LD// Declare two base classes, A and B.class A public: unsigned a; unsigned b();;class B public: unsigned a(); // note that class A likewise has a member "a" int b(); // and a member "b". Char c;;// Define class C as acquired from A and B.class C : publicly A, windy B ;Given the preceding class declarations, password such together the following is ambiguous due to the fact that it is unclear even if it is b describes the b in A or in B:
C *pc = new C;pc->b();Consider the coming before example. Due to the fact that the name a is a member the both class A and class B, the compiler cannot discern i m sorry a designates the duty to it is in called. Accessibility to a member is faint if it deserve to refer to much more than one function, object, type, or enumerator.
The compiler detects ambiguities by performing test in this order:
If access to the surname is faint (as just described), one error post is generated.
If overloaded functions are unambiguous, they are resolved.
When an expression produce an ambiguity through inheritance, you deserve to manually solve it through qualifying the surname in inquiry with its class name. To make the preceding instance compile correctly with no ambiguities, usage code such as:
C *pc = new C;pc->B::a();
When C is declared, it has the potential to reason errors once B is referenced in the limit of C. No error is issued, however, till an unqualified reference to B is in reality made in C"s scope.
It is feasible for much more than one surname (function, object, or enumerator) come be got to through an inheritance graph. Such cases are taken into consideration ambiguous with nonvirtual basic classes. Lock are also ambiguous through virtual basic classes, unless among the name "dominates" the others.
A name dominates one more name if the is characterized in both classes and one class is acquired from the other. The leading name is the name in the acquired class; this surname is provided when an ambiguity would certainly otherwise have arisen, as displayed in the adhering to example:
// deriv_Dominance.cpp// translate into with: /LDclass A public: int a;;class B : public online A public: int a();;class C : public digital A ;class D : publicly B, public C public: D() a(); // no ambiguous. B::a() restrict A::a.;
Ambiguous conversionsExplicit and also implicit conversions from pointers or references to class species can reason ambiguities. The following figure, ambiguous Conversion of needle to basic Classes, shows the following:
The statements of an object of form D.
The impact of applying the address-of operator (&) to the object. Keep in mind that the address-of operator constantly supplies the base address of the object.
The result of explicitly converting the pointer acquired using the address-of operator come the base-class form A. Keep in mind that coercing the address of the object to kind A* does no always administer the compiler with sufficient information regarding which subobject of kind A to select; in this case, 2 subobjects exist.
The conversion to type A* (pointer to A) is ambiguous because there is no way to discern i m sorry subobject of kind A is the correct one. Keep in mind that you deserve to avoid the pass out by clearly specifying which subobject you typical to use, together follows:
(A *)(B *)&d // usage B subobject.(A *)(C *)&d // usage C subobject.
Ambiguities and virtual base classesIf online base classes are used, functions, objects, types, and also enumerators have the right to be reached through multiple-inheritance paths. Since there is just one instance of the basic class, over there is no ambiguity once accessing this names.
The following number shows exactly how objects space composed making use of virtual and also nonvirtual inheritance.
See more: Which Of The Following Statements About Customer Value Is Most Accurate?
In the figure, accessing any kind of member of class A v nonvirtual base classes reasons an ambiguity; the compiler has actually no details that defines whether to use the subobject associated with B or the subobject connected with C. However, when A is specified as a online base class, there is no inquiry which subobject is being accessed.