成员函数的查找过程要涉及到三个步骤。首先,编译器查找函数的名字,然后从后续的函数选择一个最匹配的函数,最后,编译器检查函数的访问权限。
大多数与函数名不匹配的错误并不是编译器本身的问题,而是我们对成员函数查找机制的理解有问题。考虑下面的代码:
class B { public: //... void f( double ); }; class D : public B { void f( int ); }; //... D d; d.f( 12.3 ); // 令人困惑 那个成员函数f会被调用呢?我们来分析一下:
1 因为我们是在调用D的对象,所以先在D的定义中查找,得到D::f
2 选择最匹配的函数,现在只有一个,所以只能是void f( int ); (参数12。3从double转换成int 12)
这样的转换虽然是合法的,但是通常不是我们所希望的。因为有精度丢失。
3 检查访问权限,D中void f( int );是私有的,所以我们会得到一个编译错误。
从上面的例子我们可以看到:
即使在基类中有更匹配的函数存在,但是一旦编译器在派生类中找到了成员函数,(不管有没有最匹配的函数存在)它也不会
再在基类中继续查找。可以用一句话来概括,内层作用域的名字会隐藏外层的同名函数