Init
This commit is contained in:
763
cppdraft/class/derived.md
Normal file
763
cppdraft/class/derived.md
Normal 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.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)
|
||||
Reference in New Issue
Block a user