333 lines
14 KiB
Markdown
333 lines
14 KiB
Markdown
[class.virtual]
|
||
|
||
# 11 Classes [[class]](./#class)
|
||
|
||
## 11.7 Derived classes [[class.derived]](class.derived#class.virtual)
|
||
|
||
### 11.7.3 Virtual functions [class.virtual]
|
||
|
||
[1](#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)[.](#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](#note-1)*:
|
||
|
||
Virtual functions support dynamic binding and object-oriented
|
||
programming[.](#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]")[.](#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](#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[.](#2.sentence-1)
|
||
|
||
For convenience, we say that any virtual function overrides itself[.](#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[.](#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[.](#2.sentence-4)
|
||
|
||
[*Example [1](#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](#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](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3906)
|
||
|
||
[*Note [2](#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[.](#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[.](#3.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[4](#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[.](#4.sentence-1)
|
||
|
||
[*Example [3](#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](#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[.](#5.sentence-1)
|
||
|
||
[*Example [4](#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](#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"))[.](#6.sentence-1)
|
||
|
||
[*Example [5](#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](#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[.](#7.sentence-1)
|
||
|
||
[8](#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[.](#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)](#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)](#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)](#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[.](#8.sentence-2)
|
||
|
||
[9](#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[.](#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"))[.](#9.sentence-2)
|
||
|
||
[*Example [6](#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](#10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4054)
|
||
|
||
[*Note [3](#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"))[.](#10.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[11](#11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4063)
|
||
|
||
[*Note [4](#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[.](#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[.](#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[.](#11.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[12](#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"))[.](#12.sentence-1)
|
||
|
||
[13](#13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4080)
|
||
|
||
[*Example [7](#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[.](#13.sentence-2)
|
||
|
||
The final overrider of B1::A::f is B1::f and the final
|
||
overrider of B2::A::f is B2::f[.](#13.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
[14](#14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4116)
|
||
|
||
[*Example [8](#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[.](#14.sentence-2)
|
||
|
||
This example is
|
||
therefore ill-formed[.](#14.sentence-3)
|
||
|
||
Class Okay is well-formed, however,
|
||
because Okay::f is a final overrider[.](#14.sentence-4)
|
||
|
||
â *end example*]
|
||
|
||
[15](#15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4146)
|
||
|
||
[*Example [9](#example-9)*:
|
||
|
||
The following example uses the well-formed classes from above[.](#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](#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[.](#16.sentence-1)
|
||
|
||
[*Example [10](#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[.](#16.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[17](#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[.](#17.sentence-1)
|
||
|
||
Likewise,
|
||
a function that is not deleted shall not override a
|
||
deleted function[.](#17.sentence-2)
|
||
|
||
[18](#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[.](#18.sentence-1)
|
||
|
||
A consteval virtual function shall not be overridden by
|
||
a virtual function that is not consteval[.](#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)
|