Стандарт C++ 11 (1119564), страница 70
Текст из файла (страница 70)
The identicaluse with non-virtual base classes is an ambiguity; in that case there is no unique instance of the name thathides all the others. — end note ] [ Example:struct V {struct W {struct B :int f();int g();};struct C :int f(); int x; };int g(); int y; };virtual V, W {int x;int y;virtual V, W { };struct D : B, C { void glorp(); };11[ Note: The names declared in V and the left-hand instance of W are hidden by those in B, but the namesdeclared in the right-hand instance of W are not hidden at all. — end note ]void D::glorp() {x++;f();y++;g();}////////OK: B::x hides V::xOK: B::f() hides V::f()error: B::y and C’s W::yerror: B::g() and C’s W::g()§ 10.2238© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)WVBWCDFigure 6 — Name lookup— end example ]12An explicit or implicit conversion from a pointer to or an expression designating an object of a derived classto a pointer or reference to one of its base classes shall unambiguously refer to a unique object representingthe base class.
[ Example:structstructstructstructstructVABCD{{:::};};A, virtual V { };A, virtual V { };B, C { };void g() {D d;B* pb = &d;A* pa = &d;V* pv = &d;}// error, ambiguous: C’s A or B’s A?// OK: only one V subobject— end example ]13[ Note: Even if the result of name lookup is unambiguous, use of a name found in multiple subobjects mightstill be ambiguous (4.11, 5.2.5, 11.2).
— end note ] [ Example:struct B1 {void f();static void f(int);int i;};struct B2 {void f(double);};struct I1: B1 { };struct I2: B1 { };struct D: I1, I2, B2 {using B1::f;using B2::f;void g() {f();f(0);f(0.0);int B1::* mpB1 = &D::i;int D::* mpD = &D::i;//////////Ambiguous conversion of thisUnambiguous (static)Unambiguous (only one B2)UnambiguousAmbiguous conversion§ 10.2© ISO/IEC 2011 – All rights reserved239ISO/IEC 14882:2011(E)}};— end example ]10.3Virtual functions[class.virtual]1Virtual functions support dynamic binding and object-oriented programming. A class that declares orinherits a virtual function is called a polymorphic class.2If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectlyfrom Base, a member function vf with the same name, parameter-type-list (8.3.5), cv-qualification, and refqualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it isso declared) and it overrides 111 Base::vf.
For convenience we say that any virtual function overrides itself.A virtual member function C::vf of a class object S is a final overrider unless the most derived class (1.8)of which S is a base class subobject (if any) declares or inherits another member function that overrides vf.In a derived class, if a virtual member function of a base class subobject has more than one final overriderthe program is ill-formed. [ Example: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();c.C::f();}// calls B::f, the final overrider// calls A::f because of the using-declaration— end example ][ Example:structstructstructstructABCD{:::virtual void f(); };A { };A { void f(); };B, C { }; // OK: A::f and C::f are the final overriders// for the B and C subobjects, respectively— end example ]3[ Note: A virtual member function does not have to be visible to be overridden, for example,struct B {virtual void f();};111) A function with the same name but a different parameter list (Clause 13) as a virtual function is not necessarily virtualand does not override.
The use of the virtual specifier in the declaration of an overriding function is legal but redundant (hasempty semantics). Access control (Clause 11) is not considered in determining overriding.§ 10.3240© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)structvoid};structvoid};D : B {f(int);D2 : D {f();the function f(int) in class D hides the virtual function f() in its base class B; D::f(int) is not a virtualfunction. However, f() declared in class D2 has the same name and the same parameter list as B::f(), andtherefore is a virtual function that overrides the function B::f() even though B::f() is not visible in classD2. — end note ]4If a virtual function f in some class B is marked with the virt-specifier final and in a class D derived fromB a function D::f overrides B::f, the program is ill-formed. [ Example:struct B {virtual void f() const final;};struct D : B {void f() const;};// error: D::f attempts to override final B::f— end example ]5If a virtual function is marked with the virt-specifier override and does not override a member function ofa base class, the program is ill-formed.
[ Example:struct B {virtual void f(int);};struct D : B {void f(long) override;void f(int) override;};// error: wrong signature overriding B::f// OK— end example ]6Even though destructors are not inherited, a destructor in a derived class overrides a base class destructordeclared virtual; see 12.4 and 12.5.7The return type of an overriding function shall be either identical to the return type of the overriddenfunction or covariant with the classes of the functions. If a function D::f overrides a function B::f, thereturn types of the functions are covariant if they satisfy the following criteria:— both are pointers to classes, both are lvalue references to classes, or both are rvalue references toclasses112— 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 anunambiguous and accessible direct or indirect base class of the class in the return type of D::f— both pointers or references have the same cv-qualification and the class type in the return type of D::fhas the same cv-qualification as or less cv-qualification than the class type in the return type of B::f.112) Multi-level pointers to classes or references to multi-level pointers to classes are not allowed.§ 10.3© ISO/IEC 2011 – All rights reserved241ISO/IEC 14882:2011(E)8If the return type of D::f differs from the return type of B::f, the class type in the return type of D::f shallbe complete at the point of declaration of D::f or shall be the class type D.
When the overriding functionis called as the final overrider of the overridden function, its result is converted to the type returned by the(statically chosen) overridden function (5.2.2). [ Example: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 onlyD* vf4();// OK: returns pointer to derived classA* vf5();// error: returns pointer to incomplete classvoid f();};void g() {Derived d;Base* bp = &d;bp->vf1();bp->vf2();bp->f();B* p = bp->vf4();Derived* dp = &d;D* q = dp->vf4();dp->vf2();//////////////standard conversion:Derived* to Base*calls Derived::vf1()calls Base::vf2()calls Base::f() (not virtual)calls Derived::pf() and converts theresult to B*// calls Derived::pf() and does not// convert the result to B*// ill-formed: argument mismatch}— end example ]9[ Note: The interpretation of the call of a virtual function depends on the type of the object for which it iscalled (the dynamic type), whereas the interpretation of a call of a non-virtual member function dependsonly on the type of the pointer or reference denoting that object (the static type) (5.2.2).
— end note ]10[ Note: The virtual specifier implies membership, so a virtual function cannot be a nonmember (7.1.2)function. Nor can a virtual function be a static member, since a virtual function call relies on a specificobject for determining which function to invoke. A virtual function declared in one class can be declared afriend in another class. — end note ]§ 10.3242© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)11A virtual function declared in a class shall be defined, or declared pure (10.4) in that class, or both; but nodiagnostic is required (3.2).12[ Example: here are some uses of virtual functions with multiple base classes:struct A {virtual void f();};struct B1 : A {void f();};// note non-virtual derivationstruct B2 : A {void f();};struct D : B1, B2 {};// D has two separate A subobjectsvoid foo() {Dd;// A* ap = &d; // would be ill-formed: ambiguousB1* b1p = &d;A*ap = b1p;D*dp = &d;ap->f();// calls D::B1::fdp->f();// ill-formed: ambiguous}In class D above there are two occurrences of class A and hence two occurrences of the virtual memberfunction A::f.
The final overrider of B1::A::f is B1::f and the final overrider of B2::A::f is B2::f.13The following example shows a function that does not have a unique final overrider:struct A {virtual void f();};struct VB1 : virtual A {void f();};// note virtual derivationstruct VB2 : virtual A {void f();};struct Error : VB1, VB2 {};// ill-formedstruct 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.
Thisexample is therefore ill-formed. Class Okay is well formed, however, because Okay::f is a final overrider.§ 10.3© ISO/IEC 2011 – All rights reserved243ISO/IEC 14882:2011(E)14The following example uses the well-formed classes from above.struct VB1a : virtual A {};// does not declare fstruct Da : VB1a, VB2 {};void foe() {VB1a* vb1ap = new Da;vb1ap->f();}// calls VB2::f— end example ]15Explicit qualification with the scope operator (5.1) suppresses the virtual call mechanism. [ Example:class B { public: virtual void f(); };class D : public B { public: void f(); };void D::f() { /∗ ... ∗/ B::f(); }Here, the function call in D::f really does call B::f and not D::f.
— end example ]16A function with a deleted definition (8.4) shall not override a function that does not have a deleted definition.Likewise, a function that does not have a deleted definition shall not override a function with a deleteddefinition.10.4Abstract classes[class.abstract]1The abstract class mechanism supports the notion of a general concept, such as a shape, of which only moreconcrete variants, such as circle and square, can actually be used. An abstract class can also be used todefine an interface for which derived classes provide a variety of implementations.2An abstract class is a class that can be used only as a base class of some other class; no objects of an abstractclass can be created except as subobjects of a class derived from it.