A class can be derived from any number of base classes. [ Note: The use of more than one direct base class is often called multiple inheritance. — end note ] [ Example:
class A { /* ... */ }; class B { /* ... */ }; class C { /* ... */ }; class D : public A, public B, public C { /* ... */ };
— end example ]
[ Note: The order of derivation is not significant except as specified by the semantics of initialization by constructor ([class.base.init]), cleanup ([class.dtor]), and storage layout ([class.mem], [class.access.spec]). — end note ]
A class shall not be specified as a direct base class of a derived class more than once. [ Note: A class can be an indirect base class more than once and can be a direct and an indirect base class. There are limited things that can be done with such a class. The non-static data members and member functions of the direct base class cannot be referred to in the scope of the derived class. However, the static members, enumerations and types can be unambiguously referred to. — end note ] [ Example:
class X { /* ... */ }; class Y : public X, public X { /* ... */ }; // ill-formed
class L { public: int next; /* ... */ }; class A : public L { /* ... */ }; class B : public L { /* ... */ }; class C : public A, public B { void f(); /* ... */ }; // well-formed class D : public A, public L { void f(); /* ... */ }; // well-formed
— end example ]
A base class specifier that does not contain the keyword virtual, specifies a non-virtual base class. A base class specifier that contains the keyword virtual, specifies a virtual base class. For each distinct occurrence of a non-virtual base class in the class lattice of the most derived class, the most derived object ([intro.object]) shall contain a corresponding distinct base class subobject of that type. For each distinct base class that is specified virtual, the most derived object shall contain a single base class subobject of that type. [ Example: for an object of class type C, each distinct occurrence of a (non-virtual) base class L in the class lattice of C corresponds one-to-one with a distinct L subobject within the object of type C. Given the class C defined above, an object of class C will have two subobjects of class L as shown below.
In such lattices, explicit qualification can be used to specify which subobject is meant. The body of function C::f could refer to the member next of each L subobject:
void C::f() { A::next = B::next; } // well-formed
Without the A:: or B:: qualifiers, the definition of C::f above would be ill-formed because of ambiguity ([class.member.lookup]).
For another example,
class V { /* ... */ }; class A : virtual public V { /* ... */ }; class B : virtual public V { /* ... */ }; class C : public A, public B { /* ... */ };
for an object c of class type C, a single subobject of type V is shared by every base subobject of c that has a virtual base class of type V. Given the class C defined above, an object of class C will have one subobject of class V, as shown below.
A class can have both virtual and non-virtual base classes of a given type.
class B { /* ... */ }; class X : virtual public B { /* ... */ }; class Y : virtual public B { /* ... */ }; class Z : public B { /* ... */ }; class AA : public X, public Y, public Z { /* ... */ };
For an object of class AA, all virtual occurrences of base class B in the class lattice of AA correspond to a single B subobject within the object of type AA, and every other occurrence of a (non-virtual) base class B in the class lattice of AA corresponds one-to-one with a distinct B subobject within the object of type AA. Given the class AA defined above, class AA has two subobjects of class B: Z's B and the virtual B shared by X and Y, as shown below.
— end example ]