[class.member.lookup] (original) (raw)

11 Classes [class]

Name lookup can result in an ambiguity, in which case the program is ill-formed.

The following steps define the result of name lookup for a member namef in a class scope C.

The lookup set for f in C, called , consists of two component sets: the declaration set, a set of members named f; and the subobject set, a set of subobjects where declarations of these members (possibly includingusing-declarations) were found.

In the declaration set,using-declarations are replaced by the set of designated members that are not hidden or overridden by members of the derived class ([namespace.udecl]), and type declarations (including injected-class-names) are replaced by the types they designate.

is calculated as follows:

If C contains a declaration of the name f, the declaration set contains every declaration of f declared inC that satisfies the requirements of the language construct in which the lookup occurs.

[ Note

:

As another example, looking up a name in ausing-declaration includes the declaration of a class or enumeration that would ordinarily be hidden by another declaration of that name in the same scope.

end note

]

If the resulting declaration set is not empty, the subobject set contains C itself, and calculation is complete.

Otherwise (i.e., C does not contain a declaration of for the resulting declaration set is empty), is initially empty.

If C has base classes, calculate the lookup set for f in each direct base class subobject , and merge each such lookup set in turn into .

The following steps define the result of merging lookup set into the intermediate :

The result of name lookup for f in C is the declaration set of .

If it is an invalid set, the program is ill-formed.

[ Example

:

struct A { int x; };
struct B { float x; };
struct C: public A, public B { };
struct D: public virtual C { };
struct E: public virtual C { char x; }; struct F: public D, public E { };
int main() { F f; f.x = 0;
}

is unambiguous because the A and B base class subobjects of D are also base class subobjects of E, so is discarded in the first merge step.

end example

]

If the name of an overloaded function is unambiguously found, overload resolution ([over.match]) also takes place before access control.

Ambiguities can often be resolved by qualifying a name with its class name.

[ Example

:

struct A { int f(); };

struct B { int f(); };

struct C : A, B { int f() { return A::f() + B::f(); } };

end example

]

[ Note

:

A static member, a nested type or an enumerator defined in a base classT can unambiguously be found even if an object has more than one base class subobject of type T.

Two base class subobjects share the non-static member subobjects of their common virtual base classes.

end note

]

[ Example

:

struct V { int v; }; struct A { int a; static int s; enum { e }; }; struct B : A, virtual V { }; struct C : A, virtual V { }; struct D : B, C { };

void f(D* pd) { pd->v++;
pd->s++;
int i = pd->e;
pd->a++;
}

end example

]

[ Note

:

When virtual base classes are used, a hidden declaration can be reached along a path through the subobject lattice that does not pass through the hiding declaration.

This is not an ambiguity.

The identical use with non-virtual base classes is an ambiguity; in that case there is no unique instance of the name that hides all the others.

end note

]

[ Example

:

struct V { int f(); int x; }; struct W { int g(); int y; }; struct B : virtual V, W { int f(); int x; int g(); int y; }; struct C : virtual V, W { };

struct D : B, C { void glorp(); };

virt W1 W V V W2 W B B B->W1 B->V C C C->V C->W2 D D D->B D->C

Figure 6: Name lookup [fig:class.lookup]

As illustrated in Figure 6, the names declared in V and the left-hand instance of Ware hidden by those in B, but the names declared in the right-hand instance of W are not hidden at all.

void D::glorp() { x++;
f();
y++;
g();
}

end example

]

An explicit or implicit conversion from a pointer to or an expression designating an object of a derived class to a pointer or reference to one of its base classes shall unambiguously refer to a unique object representing the base class.

[ Example

:

struct V { }; struct A { }; struct B : A, virtual V { }; struct C : A, virtual V { }; struct D : B, C { };

void g() { D d; B* pb = &d; A* pa = &d;
V* pv = &d;
}

end example

]

[ 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;
} };

end example

]