764 lines
42 KiB
Markdown
764 lines
42 KiB
Markdown
[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.1 General [class.derived.general]")
|
||
: [*base-specifier-list*](#nt:base-specifier-list "11.7.1 General [class.derived.general]")
|
||
|
||
[base-specifier-list:](#nt:base-specifier-list "11.7.1 General [class.derived.general]")
|
||
[*base-specifier*](#nt:base-specifier "11.7.1 General [class.derived.general]") ...opt
|
||
[*base-specifier-list*](#nt:base-specifier-list "11.7.1 General [class.derived.general]") , [*base-specifier*](#nt:base-specifier "11.7.1 General [class.derived.general]") ...opt
|
||
|
||
[base-specifier:](#nt:base-specifier "11.7.1 General [class.derived.general]")
|
||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*class-or-decltype*](#nt:class-or-decltype "11.7.1 General [class.derived.general]")
|
||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt virtual [*access-specifier*](#nt:access-specifier "11.7.1 General [class.derived.general]")opt [*class-or-decltype*](#nt:class-or-decltype "11.7.1 General [class.derived.general]")
|
||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*access-specifier*](#nt:access-specifier "11.7.1 General [class.derived.general]") virtualopt [*class-or-decltype*](#nt:class-or-decltype "11.7.1 General [class.derived.general]")
|
||
|
||
[class-or-decltype:](#nt:class-or-decltype "11.7.1 General [class.derived.general]")
|
||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]")
|
||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") template [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")
|
||
[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")
|
||
|
||
[access-specifier:](#nt:access-specifier "11.7.1 General [class.derived.general]")
|
||
private
|
||
protected
|
||
public
|
||
|
||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") appertains to the [*base-specifier*](#nt:base-specifier "11.7.1 General [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.1 General [class.derived.general]") are those of its[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]"), and/or[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")[.](#general-2.sentence-1)
|
||
|
||
A [*class-or-decltype*](#nt:class-or-decltype "11.7.1 General [class.derived.general]") shall denote
|
||
a (possibly cv-qualified) class type that is not
|
||
an incompletely defined class ([[class.mem]](class.mem "11.4 Class members"));
|
||
any cv-qualifiers are ignored[.](#general-2.sentence-2)
|
||
|
||
The class denoted by the [*class-or-decltype*](#nt:class-or-decltype "11.7.1 General [class.derived.general]") of
|
||
a [*base-specifier*](#nt:base-specifier "11.7.1 General [class.derived.general]") is called a[*direct base class*](#def:base_class,direct "11.7.1 General [class.derived.general]") for the class being defined;
|
||
for each such [*base-specifier*](#nt:base-specifier "11.7.1 General [class.derived.general]"),
|
||
the corresponding [*direct base class relationship*](#def:relationship,direct_base_class "11.7.1 General [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.3 Simple type specifiers [dcl.type.simple]") or [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") is type-only ([[basic.lookup]](basic.lookup "6.5 Name 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.1 General [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.8 Member access control") for the meaning of[*access-specifier*](#nt:access-specifier "11.7.1 General [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.10 The 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.2 Member name lookup"))[.](#general-2.sentence-11)
|
||
|
||
The scope resolution operator :: ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3 Qualified 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.3 Accessibility 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.12 Pointer 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.4 References"))[.](#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.1 General [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.1 General [class.derived.general]") followed by an ellipsis is a pack
|
||
expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.2 Object 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*]
|
||
|
||

|
||
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.3 Initializing 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.5 Construction 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.2 Object 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.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"))[.](#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.2 Multiple 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.2 Multiple 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.2 Object 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)
|
||
|
||

|
||
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.2 Member 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 { /* ... */ };
|
||
|
||

|
||
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)
|
||
|
||

|
||
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.3 Virtual 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.3 Virtual 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.1 General")) to a declaration of F,
|
||
ignoring trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*s*,
|
||
then G [*overrides*](#def:function,virtual,override "11.7.3 Virtual 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.3 Virtual functions [class.virtual]") unless the most derived class ([[intro.object]](intro.object "6.8.2 Object 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.1 General [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.1 General [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.1 Preamble [temp.pre]") ([[dcl.decl]](dcl.decl "9.3 Declarators"))[.](#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.3 Constrained 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.1 General [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.3 Virtual 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.2 Point 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.3 Function 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.3 Function 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.3 Function 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.4 Friends")) 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.4 Abstract classes")) in that class, or both; no diagnostic is
|
||
required ([[basic.def.odr]](basic.def.odr "6.3 One-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.3 Qualified 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.6 Function 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 "12 Overloading"))
|
||
as a virtual function is not necessarily virtual and
|
||
does not override[.](#footnote-94.sentence-1)
|
||
|
||
Access control ([[class.access]](class.access "11.8 Member 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.4 Abstract classes [class.abstract]") by using a[*pure-specifier*](class.mem.general#nt:pure-specifier "11.4.1 General [class.mem.general]") ([[class.mem]](class.mem "11.4 Class 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.4 Abstract 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.2 Declarations and definitions"), [[class.mem]](class.mem "11.4 Class 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.7 Destructors")), the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") syntax ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3 Qualified 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.1 General [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.6 Functions")) or called ([[expr.call]](expr.call "7.6.1.3 Function call")),
|
||
except as specified in [[dcl.type.simple]](dcl.type.simple "9.2.9.3 Simple 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.9 Static cast"), [[expr.reinterpret.cast]](expr.reinterpret.cast "7.6.1.10 Reinterpret cast"), [[expr.const.cast]](expr.const.cast "7.6.1.11 Const cast")),
|
||
because the resulting prvalue would be of abstract class type ([[basic.lval]](basic.lval "7.2.1 Value 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.3 Virtual 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)
|