[class.mi] # 11 Classes [[class]](./#class) ## 11.7 Derived classes [[class.derived]](class.derived#class.mi) ### 11.7.2 Multiple base classes [class.mi] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3683) A class can be derived from any number of base classes[.](#1.sentence-1) [*Note [1](#note-1)*: The use of more than one direct base class is often called multiple inheritance[.](#1.sentence-2) — *end note*] [*Example [1](#example-1)*: class A { /* ... */ };class B { /* ... */ };class C { /* ... */ };class D : public A, public B, public C { /* ... */ }; — *end example*] [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3697) [*Note [2](#note-2)*: The order of derivation is not significant except as specified by the semantics of initialization by constructor ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members")), cleanup ([[class.dtor]](class.dtor "11.4.7 Destructors")), and storage layout ([[class.mem]](class.mem "11.4 Class members"), [[class.access.spec]](class.access.spec "11.8.2 Access specifiers"))[.](#2.sentence-1) — *end note*] [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3707) A class shall not be specified as a direct base class of a derived class more than once[.](#3.sentence-1) [*Note [3](#note-3)*: A class can be an indirect base class more than once and can be a direct and an indirect base class[.](#3.sentence-2) There are limited things that can be done with such a class; lookup that finds its non-static data members and member functions in the scope of the derived class will be ambiguous[.](#3.sentence-3) However, the static members, enumerations and types can be unambiguously referred to[.](#3.sentence-4) — *end note*] [*Example [2](#example-2)*: class X { /* ... */ };class Y : public X, public X { /* ... */ }; // errorclass L { public: int next; /* ... */ };class A : public L { /* ... */ };class B : public L { /* ... */ };class C : public A, public B { void f(); /* ... */ }; // well-formedclass D : public A, public L { void f(); /* ... */ }; // well-formed — *end example*] [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3734) A base class specifier that does not contain the keywordvirtual specifies a [*non-virtual base class*](#def:base_class,non-virtual "11.7.2 Multiple base classes [class.mi]")[.](#4.sentence-1) A base class specifier that contains the keyword virtual specifies a[*virtual base class*](#def:base_class,virtual "11.7.2 Multiple base classes [class.mi]")[.](#4.sentence-2) 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]](intro.object "6.8.2 Object model")) shall contain a corresponding distinct base class subobject of that type[.](#4.sentence-3) For each distinct base class that is specified virtual, the most derived object shall contain a single base class subobject of that type[.](#4.sentence-4) [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3746) [*Note [4](#note-4)*: 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[.](#5.sentence-1) Given the class C defined above, an object of class C will have two subobjects of class L as shown in Figure [4](#fig:class.nonvirt)[.](#5.sentence-2) ![SVG Image](data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE0MHB0IiB3aWR0aD0iMjI0cHQiIHZpZXdCb3g9IjAuMDAgMC4wMCAyMjQuMDAgMTQwLjAwIj4KPGcgY2xhc3M9ImdyYXBoIj4Kbm9udmlydAoKPGcgY2xhc3M9Im5vZGUiPgpMMQpMCjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KTDIKTAo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+CkEKQQo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkEtJmd0O0wxCjxwYXRoIGQ9Ik0yNywtNzYuNDFDMjcsLTgzLjMgMjcsLTkyLjkgMjcsLTEwMS40MyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KQgpCCjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KQi0mZ3Q7TDIKPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE4OSwtNzYuNDFDMTg5LC04My4zIDE4OSwtOTIuOSAxODksLTEwMS40MyIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KQwpDCjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KQy0mZ3Q7QQo8cGF0aCBzdHJva2U9ImJsYWNrIiBkPSJNOTQuMjYsLTIwLjE2QzgxLjg1LC0yOC40MyA2My4zNywtNDAuNzUgNDguOTIsLTUwLjM4IiBmaWxsPSJub25lIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpDLSZndDtCCjxwYXRoIGQ9Ik0xMjEuNzQsLTIwLjE2QzEzNC4xNSwtMjguNDMgMTUyLjYzLC00MC43NSAxNjcuMDgsLTUwLjM4IiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgo8L2c+Cjwvc3ZnPg==) Figure [4](#fig:class.nonvirt) — Non-virtual base [[fig:class.nonvirt]](./fig:class.nonvirt) In such lattices, explicit qualification can be used to specify which subobject is meant[.](#5.sentence-3) The body of function C​::​f can 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 ofC​::​f above would be ill-formed because of ambiguity ([[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup"))[.](#5.sentence-5) — *end note*] [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3772) [*Note [5](#note-5)*: In contrast, consider the case with a virtual base class:class V { /* ... */ };class A : virtual public V { /* ... */ };class B : virtual public V { /* ... */ };class C : public A, public B { /* ... */ }; ![SVG Image](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjI0cHQiIHZpZXdCb3g9IjAuMDAgMC4wMCAyMjQuMDAgMTQwLjAwIiBoZWlnaHQ9IjE0MHB0Ij4KPGcgY2xhc3M9ImdyYXBoIj4KdmlydAoKPGcgY2xhc3M9Im5vZGUiPgpWClYKPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpBCkEKPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpBLSZndDtWCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik00MC43NCwtNzYuMTZDNTMuMTUsLTg0LjQzIDcxLjYzLC05Ni43NSA4Ni4wOCwtMTA2LjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpCCkIKPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpCLSZndDtWCjxwYXRoIGQ9Ik0xNzUuMjYsLTc2LjE2QzE2Mi44NSwtODQuNDMgMTQ0LjM3LC05Ni43NSAxMjkuOTIsLTEwNi4zOCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KQwpDCjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KQy0mZ3Q7QQo8cGF0aCBzdHJva2U9ImJsYWNrIiBkPSJNOTQuMjYsLTIwLjE2QzgxLjg1LC0yOC40MyA2My4zNywtNDAuNzUgNDguOTIsLTUwLjM4IiBmaWxsPSJub25lIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpDLSZndDtCCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xMjEuNzQsLTIwLjE2QzEzNC4xNSwtMjguNDMgMTUyLjYzLC00MC43NSAxNjcuMDgsLTUwLjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgo8L2c+Cjwvc3ZnPg==) Figure [5](#fig:class.virt) — Virtual base [[fig:class.virt]](./fig:class.virt) For an object c of class type C, a single subobject of type V is shared by every base class subobject of c that has avirtual base class of type V[.](#6.sentence-1) Given the class C defined above, an object of class C will have one subobject of class V, as shown in Figure [5](#fig:class.virt)[.](#6.sentence-2) — *end note*] [7](#7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3795) [*Note [6](#note-6)*: A class can have both virtual and non-virtual base classes of a given type[.](#7.sentence-1) 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 distinctB subobject within the object of type AA[.](#7.sentence-2) 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 in Figure [6](#fig:class.virtnonvirt)[.](#7.sentence-3) ![SVG Image](data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE0MHB0IiB2aWV3Qm94PSIwLjAwIDAuMDAgMzg2LjAwIDE0MC4wMCIgd2lkdGg9IjM4NnB0Ij4KPGcgY2xhc3M9ImdyYXBoIj4KdmlydG5vbnZpcnQKCjxnIGNsYXNzPSJub2RlIj4KQjEKQgo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+CkIyCkIKPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpBQQpBQQo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+ClgKWAo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkFBLSZndDtYCjxwYXRoIGQ9Ik05NC4yNiwtMjAuMTZDODEuODUsLTI4LjQzIDYzLjM3LC00MC43NSA0OC45MiwtNTAuMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIC8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiAvPgo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+ClkKWQo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkFBLSZndDtZCjxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0xMjEuNzQsLTIwLjE2QzEzNC4xNSwtMjguNDMgMTUyLjYzLC00MC43NSAxNjcuMDgsLTUwLjM4IiBzdHJva2U9ImJsYWNrIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpaCloKPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpBQS0mZ3Q7Wgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMTM1LjQsLTE3LjA5QzE3OS4wOSwtMjYuOCAyNjQuNiwtNDUuOCAzMTMuNzgsLTU2LjczIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpYLSZndDtCMQo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNDAuNzQsLTc2LjE2QzUzLjE1LC04NC40MyA3MS42MywtOTYuNzUgODYuMDgsLTEwNi4zOCIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KWS0mZ3Q7QjEKPHBhdGggc3Ryb2tlPSJibGFjayIgZD0iTTE3NS4yNiwtNzYuMTZDMTYyLjg1LC04NC40MyAxNDQuMzcsLTk2Ljc1IDEyOS45MiwtMTA2LjM4IiBmaWxsPSJub25lIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpaLSZndDtCMgo8cGF0aCBzdHJva2U9ImJsYWNrIiBkPSJNMzUxLC03Ni40MUMzNTEsLTgzLjMgMzUxLC05Mi45IDM1MSwtMTAxLjQzIiBmaWxsPSJub25lIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgo8L2c+Cjwvc3ZnPg==) Figure [6](#fig:class.virtnonvirt) — Virtual and non-virtual base [[fig:class.virtnonvirt]](./fig:class.virtnonvirt) — *end note*]