This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

763
cppdraft/class/derived.md Normal file
View File

@@ -0,0 +1,763 @@
[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)