Стандарт C++ 98 (1119566), страница 49
Текст из файла (страница 49)
*/ };Z : public B { /* ... */ };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 toa single B subobject within the object of type AA, and every other occurrence of a (non-virtual) base class Bin the class lattice of AA corresponds one-to-one with a distinct B subobject within the object of type AA.Given the class AA defined above, class AA has two sub-objects of class B: Z’s B and the virtual B sharedby X and Y, as shown below.BXBYZAA—end example]10.2 Member name lookup1[class.member.lookup]Member name lookup determines the meaning of a name (id-expression) in a class scope (3.3.6).
Namelookup can result in an ambiguity, in which case the program is ill-formed. For an id-expression, namelookup begins in the class scope of this; for a qualified-id, name lookup begins in the scope of thenested-name-specifier. Name lookup takes place before access control (3.4, clause 11).165ISO/IEC 14882:1998(E)© ISO/IEC10.2 Member name lookup10 Derived classes2The following steps define the result of name lookup in a class scope, C.
First, every declaration for thename in the class and in each of its base class sub-objects is considered. A member name f in one subobject B hides a member name f in a sub-object A if A is a base class sub-object of B. Any declarationsthat are so hidden are eliminated from consideration.
Each of these declarations that was introduced by ausing-declaration is considered to be from each sub-object of C that is of the type containing the declaration designated by the using-declaration.96) If the resulting set of declarations are not all from sub-objectsof the same type, or the set has a nonstatic member and includes members from distinct sub-objects, there isan ambiguity and the program is ill-formed. Otherwise that set is the result of the lookup.3[Example:class Apublic:intintintintint};class Bintintpublic:intintintint};{a;(*b)();f();f(int);g();{a;b();f();g;h();h(int);class C : public A, public B {};void g(C* pc){pc->a = 1;pc->b();pc->f();pc->f(1);pc->g();pc->g = 1;pc->h();pc->h(1);}// error: ambiguous: A::a or B::a// error: ambiguous: A::b or B::b// error: ambiguous: A::f or B::f// error: ambiguous: A::f or B::f// error: ambiguous: A::g or B::g// error: ambiguous: A::g or B::g// OK// OK—end example] [Example:struct U { static int i; };struct V : U { };struct W : U { using U::i; };struct X : V, W { void foo(); };void X::foo() {i;// finds U::i in two ways: as W::i and U::i in V// no ambiguity because U::i is static}—end example]__________________96) Note that using-declarations cannot be used to resolve inherited member ambiguities; see 7.3.3.1664© ISO/IECISO/IEC 14882:1998(E)10 Derived classes10.2 Member name lookupIf the name of an overloaded function is unambiguously found, overloading resolution (13.3) also takesplace before access control.
Ambiguities can often be resolved by qualifying a name with its class name.[Example:class A {public:int f();};class B {public:int f();};class C : public A, public B {int f() { return A::f() + B::f(); }};—end example]5A static member, a nested type or an enumerator defined in a base class T can unambiguously be foundeven if an object has more than one base class subobject of type T. Two base class subobjects share thenonstatic member subobjects of their common virtual base classes. [Example:class V { public: int v; };class A {public:int a;static ints;enum { e };};class B : public A, public virtual V {};class C : public A, public virtual V {};class D : public B, public C { };void f(D* pd){pd->v++;pd->s++;int i = pd->e;pd->a++;}// OK: only one v (virtual)// OK: only one s (static)// OK: only one e (enumerator)// error, ambiguous: two as in D—end example]6When virtual base classes are used, a hidden declaration can be reached along a path through the sub-objectlattice that does not pass through the hiding declaration.
This is not an ambiguity. The identical use withnonvirtual base classes is an ambiguity; in that case there is no unique instance of the name that hides allthe others. [Example:class Vclass Wclass B{public:intint};class C{ public: int f(); int x; };{ public: int g(); int y; };: public virtual V, public Wf();g();int x;int y;: public virtual V, public W { };class D : public B, public C { void glorp(); };167ISO/IEC 14882:1998(E)© ISO/IEC10.2 Member name lookup10 Derived classesWVBWCDThe names defined in V and the left hand instance of W are hidden by those in B, but the names defined inthe right hand instance of W are not hidden at all.void D::glorp(){x++;f();y++;g();}// OK: B::x hides V::x// OK: B::f() hides V::f()// error: B::y and C’s W::y// error: B::g() and C’s W::g()—end example]7An explicit or implicit conversion from a pointer to or an lvalue of a derived class to a pointer or referenceto one of its base classes shall unambiguously refer to a unique object representing the base class.
[Example:classclassclassclassclassVABCD{{:::};};public A, public virtual V { };public A, public virtual V { };public B, public 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 sub-object—end example]10.3 Virtual 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 orindirectly from Base, a member function vf with the same name and same parameter list as Base::vf isdeclared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides97)Base::vf.
For convenience we say that any virtual function overrides itself. Then in any well-formedclass, for each virtual function declared in that class or any of its direct or indirect base classes there is aunique final overrider that overrides that function and every other overrider of that function.
The rules formember lookup (10.2) are used to determine the final overrider for a virtual function in the scope of aderived class but ignoring names introduced by using-declarations. [Example:__________________97) A function with the same name but a different parameter list (clause 13) as a virtual function is not necessarily virtual and does notoverride. The use of the virtual specifier in the declaration of an overriding function is legal but redundant (has empty semantics).Access control (clause 11) is not considered in determining overriding.168© ISO/IECISO/IEC 14882:1998(E)10 Derived classes10.3 Virtual functionsstruct 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]3[Note: 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.
However, f() declared in class D2 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() isnot visible in class D2. ]4Even though destructors are not inherited, a destructor in a derived class overrides a base class destructordeclared virtual; see 12.4 and 12.5.5The return type of an overriding function shall be either identical to the return type of the overridden function 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 or references to classes98)— 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 direct or indirect base class of the class in the return type of D::f and is accessible in D— 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.If the return type of D::f differs from the return type of B::f, the class type in the return type of D::fshall be complete at the point of declaration of D::f or shall be the class type D.
When the overridingfunction is called as the final overrider of the overridden function, its result is converted to the type returnedby the (statically chosen) overridden function (5.2.2). [Example:__________________98) Multi-level pointers to classes or references to multi-level pointers to classes are not allowed.169ISO/IEC 14882:1998(E)© ISO/IEC10.3 Virtual functions10 Derived classesclass 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) inaccessibleclass A;struct Derived : public Base {void vf1();void vf2(int);char vf3();D* vf4();A* vf5();void f();};// virtual and overrides Base::vf1()// not virtual, hides Base::vf2()// error: invalid difference in return type only// OK: returns pointer to derived class// error: returns pointer to incomplete classvoid 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 the// result to B*// calls Derived::pf() and does not// convert the result to B*// ill-formed: argument mismatch}—end example]6[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 nonvirtual member function dependsonly on the type of the pointer or reference denoting that object (the static type) (5.2.2).