Files
2025-10-25 03:02:53 +03:00

764 lines
42 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[class.derived]
# 11 Classes [[class]](./#class)
## 11.7 Derived classes [class.derived]
### [11.7.1](#general) General [[class.derived.general]](class.derived.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3511)
A list of base classes can be specified in a class definition using
the notation:
[base-clause:](#nt:base-clause "11.7.1General[class.derived.general]")
: [*base-specifier-list*](#nt:base-specifier-list "11.7.1General[class.derived.general]")
[base-specifier-list:](#nt:base-specifier-list "11.7.1General[class.derived.general]")
[*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]") ...opt
[*base-specifier-list*](#nt:base-specifier-list "11.7.1General[class.derived.general]") , [*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]") ...opt
[base-specifier:](#nt:base-specifier "11.7.1General[class.derived.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt virtual [*access-specifier*](#nt:access-specifier "11.7.1General[class.derived.general]")opt [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*access-specifier*](#nt:access-specifier "11.7.1General[class.derived.general]") virtualopt [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]")
[class-or-decltype:](#nt:class-or-decltype "11.7.1General[class.derived.general]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") template [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")
[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]")
[access-specifier:](#nt:access-specifier "11.7.1General[class.derived.general]")
private
protected
public
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") appertains to the [*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]")[.](#general-1.sentence-2)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3554)
The component names of a [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]") are those of its[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]"),[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]"), and/or[*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")[.](#general-2.sentence-1)
A [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]") shall denote
a (possibly cv-qualified) class type that is not
an incompletely defined class ([[class.mem]](class.mem "11.4Class members"));
any cv-qualifiers are ignored[.](#general-2.sentence-2)
The class denoted by the [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]") of
a [*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]") is called a[*direct base class*](#def:base_class,direct "11.7.1General[class.derived.general]") for the class being defined;
for each such [*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]"),
the corresponding [*direct base class relationship*](#def:relationship,direct_base_class "11.7.1General[class.derived.general]") is the ordered pair (D, B)
where D is the class being defined andB is the direct base class[.](#general-2.sentence-3)
The lookup for the component name of
the [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") or [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") is type-only ([[basic.lookup]](basic.lookup "6.5Name lookup"))[.](#general-2.sentence-4)
A class B is a
base class of a class D if it is a direct base class ofD or a direct base class of one of D's base classes[.](#general-2.sentence-5)
A class is an [*indirect base class*](#def:base_class,indirect "11.7.1General[class.derived.general]") of another if it is a base
class but not a direct base class[.](#general-2.sentence-6)
A class is said to be (directly or
indirectly) [*derived*](#def:derived) from its (direct or indirect) base
classes[.](#general-2.sentence-7)
[*Note [1](#general-note-1)*:
See [[class.access]](class.access "11.8Member access control") for the meaning of[*access-specifier*](#nt:access-specifier "11.7.1General[class.derived.general]")[.](#general-2.sentence-8)
— *end note*]
Members of a base class are also members of the derived class[.](#general-2.sentence-9)
[*Note [2](#general-note-2)*:
Constructors of a base class can be explicitly inherited ([[namespace.udecl]](namespace.udecl "9.10The using declaration"))[.](#general-2.sentence-10)
Base class members can be referred to in
expressions in the same manner as other members of the derived class,
unless their names are hidden or ambiguous ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"))[.](#general-2.sentence-11)
The scope resolution operator :: ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3Qualified names")) can be used
to refer to a direct or indirect base member explicitly,
even if it is hidden in the derived class[.](#general-2.sentence-12)
A derived class can itself serve as a base class subject to access
control; see [[class.access.base]](class.access.base "11.8.3Accessibility of base classes and base class members")[.](#general-2.sentence-13)
A pointer to a derived class can be
implicitly converted to a pointer to an accessible unambiguous base
class ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions"))[.](#general-2.sentence-14)
An lvalue of a derived class type can be bound
to a reference to an accessible unambiguous base
class ([[dcl.init.ref]](dcl.init.ref "9.5.4References"))[.](#general-2.sentence-15)
— *end note*]
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3609)
The [*base-specifier-list*](#nt:base-specifier-list "11.7.1General[class.derived.general]") specifies the type of the[*base class subobjects*](#def:base_class_subobjects) contained in an
object of the derived class type[.](#general-3.sentence-1)
[*Example [1](#general-example-1)*: struct Base {int a, b, c;};
struct Derived : Base {int b;};
struct Derived2 : Derived {int c;};
Here, an object of class Derived2 will have a subobject of classDerived which in turn will have a subobject of classBase[.](#general-3.sentence-2)
— *end example*]
[4](#general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3637)
A [*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]") followed by an ellipsis is a pack
expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#general-4.sentence-1)
[5](#general-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3641)
The order in which the base class subobjects are allocated in the most
derived object ([[intro.object]](intro.object "6.8.2Object model")) is unspecified[.](#general-5.sentence-1)
[*Note [3](#general-note-3)*:
A derived class and its base class subobjects can be represented by a
directed acyclic graph (DAG) where an arrow means “directly derived
from” (see Figure [3](#fig:class.dag))[.](#general-5.sentence-2)
An arrow need not have a physical representation in memory[.](#general-5.sentence-3)
A DAG of subobjects is often referred to as a “subobject lattice”[.](#general-5.sentence-4)
— *end note*]
![SVG Image](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzlwdCIgaGVpZ2h0PSIxNDBwdCIgdmlld0JveD0iMC4wMCAwLjAwIDc5LjAwIDE0MC4wMCI+CjxnIGNsYXNzPSJncmFwaCI+CmRhZwoKPGcgY2xhc3M9Im5vZGUiPgpCYXNlCkJhc2UKPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpEZXJpdmVkMQpEZXJpdmVkMQo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkRlcml2ZWQxLSZndDtCYXNlCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0zNS41LC03Ni40MUMzNS41LC04My4zIDM1LjUsLTkyLjkgMzUuNSwtMTAxLjQzIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpEZXJpdmVkMgpEZXJpdmVkMgo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkRlcml2ZWQyLSZndDtEZXJpdmVkMQo8cGF0aCBzdHJva2U9ImJsYWNrIiBmaWxsPSJub25lIiBkPSJNMzUuNSwtMjAuNDFDMzUuNSwtMjcuMyAzNS41LC0zNi45IDM1LjUsLTQ1LjQzIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgo8L2c+Cjwvc3ZnPg==)
Figure [3](#fig:class.dag) — Directed acyclic graph [[fig:class.dag]](./fig:class.dag)
[6](#general-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3661)
[*Note [4](#general-note-4)*:
Initialization of objects representing base classes can be specified in
constructors; see [[class.base.init]](class.base.init "11.9.3Initializing bases and members")[.](#general-6.sentence-1)
— *end note*]
[7](#general-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3667)
[*Note [5](#general-note-5)*:
A base class subobject can have a layout different
from the layout of a most derived object of the same type[.](#general-7.sentence-1)
A base class
subobject can have a polymorphic behavior ([[class.cdtor]](class.cdtor "11.9.5Construction and destruction"))
different from the polymorphic behavior of a most derived object of the
same type[.](#general-7.sentence-2)
A base class subobject can be of zero size;
however, two subobjects that have the same class type and that belong to
the same most derived object cannot be allocated at the same
address ([[intro.object]](intro.object "6.8.2Object model"))[.](#general-7.sentence-3)
— *end note*]
### [11.7.2](#class.mi) Multiple base classes [[class.mi]](class.mi)
[1](#class.mi-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3683)
A class can be derived from any number of base classes[.](#class.mi-1.sentence-1)
[*Note [1](#class.mi-note-1)*:
The use of more than one direct base class is often called multiple inheritance[.](#class.mi-1.sentence-2)
— *end note*]
[*Example [1](#class.mi-example-1)*: class A { /* ... */ };class B { /* ... */ };class C { /* ... */ };class D : public A, public B, public C { /* ... */ }; — *end example*]
[2](#class.mi-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3697)
[*Note [2](#class.mi-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.3Initializing bases and members")),
cleanup ([[class.dtor]](class.dtor "11.4.7Destructors")), and storage
layout ([[class.mem]](class.mem "11.4Class members"), [[class.access.spec]](class.access.spec "11.8.2Access specifiers"))[.](#class.mi-2.sentence-1)
— *end note*]
[3](#class.mi-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[.](#class.mi-3.sentence-1)
[*Note [3](#class.mi-note-3)*:
A class can be an indirect base class more than once and can be a direct
and an indirect base class[.](#class.mi-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[.](#class.mi-3.sentence-3)
However, the static members, enumerations and types can be
unambiguously referred to[.](#class.mi-3.sentence-4)
— *end note*]
[*Example [2](#class.mi-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](#class.mi-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.2Multiple base classes[class.mi]")[.](#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.2Multiple base classes[class.mi]")[.](#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.2Object model")) shall contain a
corresponding distinct base class subobject of that type[.](#class.mi-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[.](#class.mi-4.sentence-4)
[5](#class.mi-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3746)
[*Note [4](#class.mi-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[.](#class.mi-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)[.](#class.mi-5.sentence-2)
![SVG Image](data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwLjAwIDAuMDAgMjI0LjAwIDE0MC4wMCIgaGVpZ2h0PSIxNDBwdCIgd2lkdGg9IjIyNHB0Ij4KPGcgY2xhc3M9ImdyYXBoIj4Kbm9udmlydAoKPGcgY2xhc3M9Im5vZGUiPgpMMQpMCjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KTDIKTAo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+CkEKQQo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkEtJmd0O0wxCjxwYXRoIHN0cm9rZT0iYmxhY2siIGQ9Ik0yNywtNzYuNDFDMjcsLTgzLjMgMjcsLTkyLjkgMjcsLTEwMS40MyIgZmlsbD0ibm9uZSIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KQgpCCjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KQi0mZ3Q7TDIKPHBhdGggZmlsbD0ibm9uZSIgZD0iTTE4OSwtNzYuNDFDMTg5LC04My4zIDE4OSwtOTIuOSAxODksLTEwMS40MyIgc3Ryb2tlPSJibGFjayIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KQwpDCjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KQy0mZ3Q7QQo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNOTQuMjYsLTIwLjE2QzgxLjg1LC0yOC40MyA2My4zNywtNDAuNzUgNDguOTIsLTUwLjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpDLSZndDtCCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xMjEuNzQsLTIwLjE2QzEzNC4xNSwtMjguNDMgMTUyLjYzLC00MC43NSAxNjcuMDgsLTUwLjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgo8L2c+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[.](#class.mi-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.2Member name lookup"))[.](#class.mi-5.sentence-5)
— *end note*]
[6](#class.mi-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3772)
[*Note [5](#class.mi-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,PHN2ZyB2aWV3Qm94PSIwLjAwIDAuMDAgMjI0LjAwIDE0MC4wMCIgaGVpZ2h0PSIxNDBwdCIgd2lkdGg9IjIyNHB0Ij4KPGcgY2xhc3M9ImdyYXBoIj4KdmlydAoKPGcgY2xhc3M9Im5vZGUiPgpWClYKPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpBCkEKPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpBLSZndDtWCjxwYXRoIGQ9Ik00MC43NCwtNzYuMTZDNTMuMTUsLTg0LjQzIDcxLjYzLC05Ni43NSA4Ni4wOCwtMTA2LjM4IiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpCCkIKPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpCLSZndDtWCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNzUuMjYsLTc2LjE2QzE2Mi44NSwtODQuNDMgMTQ0LjM3LC05Ni43NSAxMjkuOTIsLTEwNi4zOCIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KQwpDCjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KQy0mZ3Q7QQo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNOTQuMjYsLTIwLjE2QzgxLjg1LC0yOC40MyA2My4zNywtNDAuNzUgNDguOTIsLTUwLjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpDLSZndDtCCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xMjEuNzQsLTIwLjE2QzEzNC4xNSwtMjguNDMgMTUyLjYzLC00MC43NSAxNjcuMDgsLTUwLjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgo8L2c+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[.](#class.mi-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)[.](#class.mi-6.sentence-2)
— *end note*]
[7](#class.mi-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3795)
[*Note [6](#class.mi-note-6)*:
A class can have both virtual and non-virtual base classes of a given
type[.](#class.mi-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[.](#class.mi-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)[.](#class.mi-7.sentence-3)
![SVG Image](data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwLjAwIDAuMDAgMzg2LjAwIDE0MC4wMCIgaGVpZ2h0PSIxNDBwdCIgd2lkdGg9IjM4NnB0Ij4KPGcgY2xhc3M9ImdyYXBoIj4KdmlydG5vbnZpcnQKCjxnIGNsYXNzPSJub2RlIj4KQjEKQgo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+CkIyCkIKPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpBQQpBQQo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+ClgKWAo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkFBLSZndDtYCjxwYXRoIHN0cm9rZT0iYmxhY2siIGZpbGw9Im5vbmUiIGQ9Ik05NC4yNiwtMjAuMTZDODEuODUsLTI4LjQzIDYzLjM3LC00MC43NSA0OC45MiwtNTAuMzgiIC8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiAvPgo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+ClkKWQo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkFBLSZndDtZCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xMjEuNzQsLTIwLjE2QzEzNC4xNSwtMjguNDMgMTUyLjYzLC00MC43NSAxNjcuMDgsLTUwLjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpaCloKPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpBQS0mZ3Q7Wgo8cGF0aCBkPSJNMTM1LjQsLTE3LjA5QzE3OS4wOSwtMjYuOCAyNjQuNiwtNDUuOCAzMTMuNzgsLTU2LjczIiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpYLSZndDtCMQo8cGF0aCBkPSJNNDAuNzQsLTc2LjE2QzUzLjE1LC04NC40MyA3MS42MywtOTYuNzUgODYuMDgsLTEwNi4zOCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KWS0mZ3Q7QjEKPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE3NS4yNiwtNzYuMTZDMTYyLjg1LC04NC40MyAxNDQuMzcsLTk2Ljc1IDEyOS45MiwtMTA2LjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpaLSZndDtCMgo8cGF0aCBkPSJNMzUxLC03Ni40MUMzNTEsLTgzLjMgMzUxLC05Mi45IDM1MSwtMTAxLjQzIiBzdHJva2U9ImJsYWNrIiBmaWxsPSJub25lIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgo8L2c+Cjwvc3ZnPg==)
Figure [6](#fig:class.virtnonvirt) — Virtual and non-virtual base [[fig:class.virtnonvirt]](./fig:class.virtnonvirt)
— *end note*]
### [11.7.3](#class.virtual) Virtual functions [[class.virtual]](class.virtual)
[1](#class.virtual-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3830)
A non-static member function is a [*virtual function*](#def:function,virtual "11.7.3Virtual functions[class.virtual]") if it is first declared with the keyword virtual or
if it overrides a virtual member function declared in a base class
(see below)[.](#class.virtual-1.sentence-1)[92](#footnote-92 "The use of the virtual specifier in the declaration of an overriding function is valid but redundant (has empty semantics).")
[*Note [1](#class.virtual-note-1)*:
Virtual functions support dynamic binding and object-oriented
programming[.](#class.virtual-1.sentence-2)
— *end note*]
A class with a virtual member function is called a [*polymorphic class*](#def:class,polymorphic "11.7.3Virtual functions[class.virtual]")[.](#class.virtual-1.sentence-3)[93](#footnote-93 "If all virtual functions are immediate functions, the class is still polymorphic even if its internal representation does not otherwise require any additions for that polymorphic behavior.")
[2](#class.virtual-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3853)
If a virtual member function F is declared in a class B, and,
in a class D derived (directly or indirectly) from B,
a declaration of a member function G corresponds ([[basic.scope.scope]](basic.scope.scope "6.4.1General")) to a declaration of F,
ignoring trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")*s*,
then G [*overrides*](#def:function,virtual,override "11.7.3Virtual functions[class.virtual]")[94](#footnote-94 "A function with the same name but a different parameter list ([over]) as a virtual function is not necessarily virtual and does not override. Access control ([class.access]) is not considered in determining overriding.")F[.](#class.virtual-2.sentence-1)
For convenience, we say that any virtual function overrides itself[.](#class.virtual-2.sentence-2)
A virtual member function V of a class object S is a [*final
overrider*](#def:final_overrider "11.7.3Virtual functions[class.virtual]") unless the most derived class ([[intro.object]](intro.object "6.8.2Object model")) of which S is a
base class subobject (if any) has another member function that overrides V[.](#class.virtual-2.sentence-3)
In a derived class, if a virtual member function of a base class subobject
has more than one final overrider, the program is ill-formed[.](#class.virtual-2.sentence-4)
[*Example [1](#class.virtual-example-1)*: struct A {virtual void f();};struct B : virtual A {virtual void f();};struct C : B , virtual A {using A::f;};
void foo() { C c;
c.f(); // calls B::f, the final overrider c.C::f(); // calls A::f because of the using-declaration} — *end example*]
[*Example [2](#class.virtual-example-2)*: struct A { virtual void f(); };struct B : A { };struct C : A { void f(); };struct D : B, C { }; // OK, A::f and C::f are the final overriders// for the B and C subobjects, respectively — *end example*]
[3](#class.virtual-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3906)
[*Note [2](#class.virtual-note-2)*:
A virtual member function does not have to be visible to be overridden,
for example,struct B {virtual void f();};struct D : B {void f(int);};struct D2 : D {void f();}; the function f(int) in class D hides the virtual
function f() in its base class B; D::f(int) is
not a virtual function[.](#class.virtual-3.sentence-1)
However, f() declared in classD2 has the same name and the same parameter list asB::f(), and therefore is a virtual function that overrides the
function B::f() even though B::f() is not visible in
class D2[.](#class.virtual-3.sentence-2)
— *end note*]
[4](#class.virtual-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3930)
If a virtual function f in some class B is marked with the[*virt-specifier*](class.mem.general#nt:virt-specifier "11.4.1General[class.mem.general]") final and in a class D derived from B a function D::f overrides B::f, the program is ill-formed[.](#class.virtual-4.sentence-1)
[*Example [3](#class.virtual-example-3)*: struct B {virtual void f() const final;};
struct D : B {void f() const; // error: D::f attempts to override final B::f}; — *end example*]
[5](#class.virtual-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3946)
If a virtual function is marked with the [*virt-specifier*](class.mem.general#nt:virt-specifier "11.4.1General[class.mem.general]") override and
does not override a member function of a base class, the program is ill-formed[.](#class.virtual-5.sentence-1)
[*Example [4](#class.virtual-example-4)*: struct B {virtual void f(int);};
struct D : B {virtual void f(long) override; // error: wrong signature overriding B::fvirtual void f(int) override; // OK}; — *end example*]
[6](#class.virtual-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3962)
A virtual function shall not have a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") ([[dcl.decl]](dcl.decl "9.3Declarators"))[.](#class.virtual-6.sentence-1)
[*Example [5](#class.virtual-example-5)*: template<typename T>struct A {virtual void f() requires true; // error: virtual function cannot be constrained ([[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations"))}; — *end example*]
[7](#class.virtual-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3973)
The [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]"), or lack thereof, of an overriding function
shall be the same as that of the overridden function[.](#class.virtual-7.sentence-1)
[8](#class.virtual-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3977)
The return type of an overriding function shall be either identical to
the return type of the overridden function or [*covariant*](#def:return_type,covariant "11.7.3Virtual functions[class.virtual]") with
the classes of the functions[.](#class.virtual-8.sentence-1)
If a function D::f overrides a
function B::f, the return types of the functions are covariant
if they satisfy the following criteria:
- [(8.1)](#class.virtual-8.1)
both are pointers to classes, both are lvalue references to
classes, or both are rvalue references to classes[95](#footnote-95 "Multi-level pointers to classes or references to multi-level pointers to classes are not allowed.")
- [(8.2)](#class.virtual-8.2)
the class in the return type of B::f is the same class as
the class in the return type of D::f, or is an unambiguous and
accessible direct or indirect base class of the class in the return type
of D::f
- [(8.3)](#class.virtual-8.3)
both pointers or references have the same cv-qualification and the
class type in the return type of D::f has the same
cv-qualification as or less cv-qualification than the class type in the
return type of B::f[.](#class.virtual-8.sentence-2)
[9](#class.virtual-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4002)
If the class type in the covariant return type of D::f differs from that ofB::f, the class type in the return type of D::f shall be
complete at the locus ([[basic.scope.pdecl]](basic.scope.pdecl "6.4.2Point of declaration")) of the overriding declaration or shall be the
class type D[.](#class.virtual-9.sentence-1)
When the overriding function is called as the
final overrider of the overridden function, its result is converted to
the type returned by the (statically chosen) overridden
function ([[expr.call]](expr.call "7.6.1.3Function call"))[.](#class.virtual-9.sentence-2)
[*Example [6](#class.virtual-example-6)*: class B { };class D : private B { friend class Derived; };struct Base {virtual void vf1(); virtual void vf2(); virtual void vf3(); virtual B* vf4(); virtual B* vf5(); void f();};
struct No_good : public Base { D* vf4(); // error: B (base class of D) inaccessible};
class A;struct Derived : public Base {void vf1(); // virtual and overrides Base::vf1()void vf2(int); // not virtual, hides Base::vf2()char vf3(); // error: invalid difference in return type only D* vf4(); // OK, returns pointer to derived class A* vf5(); // error: returns pointer to incomplete classvoid f();};
void g() { Derived d;
Base* bp = &d; // standard conversion:// Derived* to Base* bp->vf1(); // calls Derived::vf1() bp->vf2(); // calls Base::vf2() bp->f(); // calls Base::f() (not virtual) B* p = bp->vf4(); // calls Derived::vf4() and converts the// result to B* Derived* dp = &d;
D* q = dp->vf4(); // calls Derived::vf4() and does not// convert the result to B* dp->vf2(); // error: argument mismatch} — *end example*]
[10](#class.virtual-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4054)
[*Note [3](#class.virtual-note-3)*:
The interpretation of the call of a virtual function depends on the type
of the object for which it is called (the dynamic type), whereas the
interpretation of a call of a non-virtual member function depends only
on the type of the pointer or reference denoting that object (the static
type) ([[expr.call]](expr.call "7.6.1.3Function call"))[.](#class.virtual-10.sentence-1)
— *end note*]
[11](#class.virtual-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4063)
[*Note [4](#class.virtual-note-4)*:
The virtual specifier implies membership, so a virtual function
cannot be a non-member ([[dcl.fct.spec]](dcl.fct.spec "9.2.3Function specifiers")) function[.](#class.virtual-11.sentence-1)
Nor can a virtual
function be a static member, since a virtual function call relies on a
specific object for determining which function to invoke[.](#class.virtual-11.sentence-2)
A virtual
function declared in one class can be declared a friend ([[class.friend]](class.friend "11.8.4Friends")) in
another class[.](#class.virtual-11.sentence-3)
— *end note*]
[12](#class.virtual-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4073)
A virtual function declared in a class shall be defined, or declared
pure ([[class.abstract]](#class.abstract "11.7.4Abstract classes")) in that class, or both; no diagnostic is
required ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))[.](#class.virtual-12.sentence-1)
[13](#class.virtual-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4080)
[*Example [7](#class.virtual-example-7)*:
Here are some uses of virtual functions with multiple base classes:struct A {virtual void f();};
struct B1 : A { // note non-virtual derivationvoid f();};
struct B2 : A {void f();};
struct D : B1, B2 { // D has two separate A subobjects};
void foo() { D d;// A* ap = &d; // would be ill-formed: ambiguous B1* b1p = &d;
A* ap = b1p;
D* dp = &d;
ap->f(); // calls D::B1::f dp->f(); // error: ambiguous}
In class D above there are two occurrences of class A and hence two occurrences of the virtual member function A::f[.](#class.virtual-13.sentence-2)
The final overrider of B1::A::f is B1::f and the final
overrider of B2::A::f is B2::f[.](#class.virtual-13.sentence-3)
— *end example*]
[14](#class.virtual-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4116)
[*Example [8](#class.virtual-example-8)*:
The following example shows a function that does not have a unique final
overrider:struct A {virtual void f();};
struct VB1 : virtual A { // note virtual derivationvoid f();};
struct VB2 : virtual A {void f();};
struct Error : VB1, VB2 { // error};
struct Okay : VB1, VB2 {void f();};
Both VB1::f and VB2::f override A::f but there
is no overrider of both of them in class Error[.](#class.virtual-14.sentence-2)
This example is
therefore ill-formed[.](#class.virtual-14.sentence-3)
Class Okay is well-formed, however,
because Okay::f is a final overrider[.](#class.virtual-14.sentence-4)
— *end example*]
[15](#class.virtual-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4146)
[*Example [9](#class.virtual-example-9)*:
The following example uses the well-formed classes from above[.](#class.virtual-15.sentence-1)
struct VB1a : virtual A { // does not declare f};
struct Da : VB1a, VB2 {};
void foe() { VB1a* vb1ap = new Da;
vb1ap->f(); // calls VB2::f} — *end example*]
[16](#class.virtual-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4163)
Explicit qualification with the scope operator ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3Qualified names"))
suppresses the virtual call mechanism[.](#class.virtual-16.sentence-1)
[*Example [10](#class.virtual-example-10)*: class B { public: virtual void f(); };class D : public B { public: void f(); };
void D::f() { /* ... */ B::f(); }
Here, the function call inD::f really does callB::f and notD::f[.](#class.virtual-16.sentence-2)
— *end example*]
[17](#class.virtual-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4184)
A deleted function ([[dcl.fct.def]](dcl.fct.def "9.6Function definitions")) shall
not override a function that is not deleted[.](#class.virtual-17.sentence-1)
Likewise,
a function that is not deleted shall not override a
deleted function[.](#class.virtual-17.sentence-2)
[18](#class.virtual-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4191)
A consteval virtual function shall not override
a virtual function that is not consteval[.](#class.virtual-18.sentence-1)
A consteval virtual function shall not be overridden by
a virtual function that is not consteval[.](#class.virtual-18.sentence-2)
[92)](#footnote-92)[92)](#footnoteref-92)
The use of the virtual specifier in the
declaration of an overriding function is valid but redundant (has empty
semantics)[.](#footnote-92.sentence-1)
[93)](#footnote-93)[93)](#footnoteref-93)
If
all virtual functions are immediate functions,
the class is still polymorphic even if
its internal representation does not otherwise require
any additions for that polymorphic behavior[.](#footnote-93.sentence-1)
[94)](#footnote-94)[94)](#footnoteref-94)
A function
with the same name but a different parameter list ([[over]](over "12Overloading"))
as a virtual function is not necessarily virtual and
does not override[.](#footnote-94.sentence-1)
Access control ([[class.access]](class.access "11.8Member access control")) is not considered in
determining overriding[.](#footnote-94.sentence-2)
[95)](#footnote-95)[95)](#footnoteref-95)
Multi-level pointers to classes or references to multi-level pointers to
classes are not allowed[.](#footnote-95.sentence-1)
### [11.7.4](#class.abstract) Abstract classes [[class.abstract]](class.abstract)
[1](#class.abstract-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4199)
[*Note [1](#class.abstract-note-1)*:
The abstract class mechanism supports the notion of a general concept,
such as a shape, of which only more concrete variants, such ascircle and square, can actually be used[.](#class.abstract-1.sentence-1)
An abstract
class can also be used to define an interface for which derived classes
provide a variety of implementations[.](#class.abstract-1.sentence-2)
— *end note*]
[2](#class.abstract-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4208)
A virtual function is specified as
a [*pure virtual function*](#def:function,virtual,pure "11.7.4Abstract classes[class.abstract]") by using a[*pure-specifier*](class.mem.general#nt:pure-specifier "11.4.1General[class.mem.general]") ([[class.mem]](class.mem "11.4Class members")) in the function declaration
in the class definition[.](#class.abstract-2.sentence-1)
[*Note [2](#class.abstract-note-2)*:
Such a function might be inherited: see below[.](#class.abstract-2.sentence-2)
— *end note*]
A class is an [*abstract class*](#def:class,abstract "11.7.4Abstract classes[class.abstract]") if it has at least one pure virtual function[.](#class.abstract-2.sentence-3)
[*Note [3](#class.abstract-note-3)*:
An abstract class can be used only as a base class of some other class;
no objects of an abstract class can be created
except as subobjects of a class
derived from it ([[basic.def]](basic.def "6.2Declarations and definitions"), [[class.mem]](class.mem "11.4Class members"))[.](#class.abstract-2.sentence-4)
— *end note*]
A pure virtual function need be defined only if called with, or as if
with ([[class.dtor]](class.dtor "11.4.7Destructors")), the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") syntax ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3Qualified names"))[.](#class.abstract-2.sentence-5)
[*Example [1](#class.abstract-example-1)*: class point { /* ... */ };class shape { // abstract class point center;public: point where() { return center; }void move(point p) { center=p; draw(); }virtual void rotate(int) = 0; // pure virtualvirtual void draw() = 0; // pure virtual}; — *end example*]
[*Note [4](#class.abstract-note-4)*:
A function declaration cannot provide both a [*pure-specifier*](class.mem.general#nt:pure-specifier "11.4.1General[class.mem.general]") and a definition[.](#class.abstract-2.sentence-6)
— *end note*]
[*Example [2](#class.abstract-example-2)*: struct C {virtual void f() = 0 { }; // error}; — *end example*]
[3](#class.abstract-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4253)
[*Note [5](#class.abstract-note-5)*:
An abstract class type cannot be used
as a parameter or return type of
a function being defined ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) or called ([[expr.call]](expr.call "7.6.1.3Function call")),
except as specified in [[dcl.type.simple]](dcl.type.simple "9.2.9.3Simple type specifiers")[.](#class.abstract-3.sentence-1)
Further, an abstract class type cannot be used as
the type of an explicit type conversion ([[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"), [[expr.reinterpret.cast]](expr.reinterpret.cast "7.6.1.10Reinterpret cast"), [[expr.const.cast]](expr.const.cast "7.6.1.11Const cast")),
because the resulting prvalue would be of abstract class type ([[basic.lval]](basic.lval "7.2.1Value category"))[.](#class.abstract-3.sentence-2)
However, pointers and references to abstract class types
can appear in such contexts[.](#class.abstract-3.sentence-3)
— *end note*]
[4](#class.abstract-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4267)
A class is abstract if it has at least one pure virtual
function for which the final overrider is pure virtual[.](#class.abstract-4.sentence-1)
[*Example [3](#class.abstract-example-3)*: class ab_circle : public shape {int radius;public:void rotate(int) { }// ab_circle::draw() is a pure virtual};
Since shape::draw() is a pure virtual functionab_circle::draw() is a pure virtual by default[.](#class.abstract-4.sentence-2)
The alternative
declaration,class circle : public shape {int radius;public:void rotate(int) { }void draw(); // a definition is required somewhere}; would make class circle non-abstract and a definition ofcircle::draw() must be provided[.](#class.abstract-4.sentence-3)
— *end example*]
[5](#class.abstract-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4296)
[*Note [6](#class.abstract-note-6)*:
An abstract class can be derived from a class that is not abstract, and
a pure virtual function can override a virtual function which is not
pure[.](#class.abstract-5.sentence-1)
— *end note*]
[6](#class.abstract-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4303)
Member functions can be called from a constructor (or destructor) of an
abstract class;the effect of making a virtual call ([[class.virtual]](#class.virtual "11.7.3Virtual functions")) to a pure
virtual function directly or indirectly for the object being created (or
destroyed) from such a constructor (or destructor) is undefined[.](#class.abstract-6.sentence-1)