Aug. 10, 2010, 7:07 p.m.
posted by nogood
Item 24. Member Function LookupWhen you call a member function, there are three steps involved. First, the compiler looks up the name of the function. Second, it chooses the best matching function from the available candidates. Third, it checks that you have access to the matched function. That's it. Admittedly, each of these steps (especially the first two; see Argument Dependent Lookup [25, 89] and Operator Function Lookup [26, 91]) can be complex, but the overall function matching mechanism is as simple as one, two, three. Most errors related to function matching stem not from misunderstanding the compiler's complex name lookup and overloaded function matching algorithms but from misunderstanding the simple, sequential nature of these three steps. Consider the following:
class B {
public:
//...
void f( double );
};
class D : public B {
void f( int );
};
//...
D d;
d.f( 12.3 ); // confusing
Which member f is called?
The existence of a better-matching, accessible function in the base class is immaterial, because the compiler does not continue searching for a name in outer scopes once it has found one in an inner scope. An inner scope name hides the same name in an outer scope; it does not overload it as it does in Java. In fact, the name does not even have to be the name of a function:
class E : public D {
int f;
};
//...
E e;
e.f( 12 ); // error!
In this case, we have a compile-time error because our lookup of the name f in the scope of E netted us a data member, not a member function. This is, by the way, one of many reasons to establish and adhere to a simple naming convention. If the data member E::f had been named f_ or m_f, it would not have hidden the inherited base class function f. |
- Comment