调用一个普通成员函数 ,涉及三个步骤:第一步,编译器查找函数的名字 ;第二步,从可用候选者中选择最佳匹配函数;第三步,检查是否具有访问该匹配函数的权限。
一旦在内层作用域中找到匹配的,编译器就不会到外层作用域中继续查找了,即使在外层中有匹配的名字.内层作用域中的名字会隐藏 外层作用域中相同的名字。 在这一点上,c++不同于java;java中,内层作用域中的方法名字和外层作用域中的同名方法属于重载关系。
class App
{
public:
//........
void find(double);
};
class DerivedApp : public App
{
void find();
};
//..........
DerivedApp dApp;
dApp.find(13.4); //compiler error
这个例子中会有编译错误,知道为什么了吧?
实参相依的查找 (Argument Dependent Lookup)也是调用过程中一个重要原则。ADL背后蕴含的思想非常简单,当查找一个函数调用表达式中的函数的名字时,编译器也会到“包含函数调用实参的类型”的名字空间中检查.
要注意区分的是, ADL是关于函数如何被调用的一个属性,而重载则是关于函数如何声明的一个属性。
此外,操作符函数的查找 还有点不一样的地方。
有时候看上去好像一个成员操作符重载了一个非成员操作符,其实并非如此。重载操作符后,有两种调用的方法,一种是只用到操作符,另外一种是和普通成员函数一样调用,然而两种方法的查找规则是不同的。如果使用函数调用语法,应用的是普通的查找规则,而直接使用操作符的机制则不相同。
class X{ X operator%(const X&)const;};
X x,y;
x % y; //中缀调用
x.operator%(y); //成员函数调用
对于中缀操作符调用来说,编译器不仅会考虑成员操作符,也会考虑非成员操作符。即,当确定将哪些函数纳入重载解析考虑范围时,中缀操作符中左参数(可能只有一个左参数,而没有右参数)的类的作用域和全局作用域都 被考虑在内。ADL则将这个过程扩展到被操作符实参所带入的其他名字空间中的候选操作符函数。
注意,成员操作符和非成员操作符并非重载,而是编译器在两个不同的地方查找候选函数。重载是关于函数在同一个作用域中被声明的一个静态属性,而ADL和中缀操作符函数查找都属于提供给函数调用的实参的属性。
参考:
关于hide可以参考如下链接
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Foverload_member_fn_base_derived.htm