认清C++语言之《成员函数查找》

成员函数查找:

1)  调用一个成员函数时,涉及三个步骤:一是编译器查找函数的名字;二是从可用候选者中选择最佳匹配函数;三是检查是否具有访问该匹配函数的权限。例如:

class App

{

public:

//........

void find(double);

};

 

class ACEApp : public App

{

void find(int);

};

 

//..........

ACEApp aa;

aa.find(13.4);                     //容易混淆

 

上面代码调用的是哪一个成员find?分析如下:

步骤一:查找函数名字。从ACEApp的作用域开始查找并且立即定位到ACEApp::find上。

步骤二:从可用候选者中选择最佳匹配函数。因为我们只有一个候选者,因此会尝试匹配该函数,通过将实参13.4double转换为int做到这一点。

步骤三:检查访问权限。我们可能得到一个错误,因为ACEApp::find是私有成员。

 

匹配的过程中,编译器一旦在内层作用域中找到一个,它就不会到外层作用域中继续查找该名字。内层作用域的名字会隐藏外层作用域中相同的名字。这一点和Java不同,因为在Java中,内层作用域中的方法名字和外层作用域中同名方法属于重载关系。

 

实际上,该名字甚至可以不是一个函数的名字:

class HWApp : public ACEApp

{

    int f;

};

//..........

HWApp ha;

ha.f(12);                        //Err

 

 

实参相依的查找:

1)  实参相依的查找(Argument Dependent LookupADL):当查找一个函数调用表达式中的函数名字时,编译器也会到“包含函数调用实参的类型”的名字空间中检查。例如:

namespace ACE

{

class Hw {.....};

void find(const Hw &);

Hw operator +(const Hw &, const Hw &);

class String {....};

std::ostream operator <<(std::ostream &, const String &);

};

//......

void AceFunc()

{

ACE::Hw hw;

find(hw);                                     //调用ACE::find

hw = hw + hw;     //调用ACE::operator +

}

 

普通的查找是不会发现函数ACE::find的,因为它嵌套在一个名字空间内,并且对find的使用需要以该名字空间的名字加以限定。然而,由于实参hw的类型被定义于ACE名字空间中,因此,编译器也会到该名字空间中检查候选函数。

2) 实际上,很多程序员广泛地使用了ADL却没意识到这一点,例如:

ACE::String name("hw");

std::out <<"Hello, "<<name;

在这个例子中,对operator<<的第一个使用极可能调用的是类模板std::basic_ostream的一个成员函数,而第二个则是对位于ACE名字空间中重载的operator<<的非成员函数的调用。

 

 

操作符函数查找:

1)  有时看上去好像一个成员操作符函数重载了一个非成员的操作符,事实上并非如此,这不是重载,而是不同的查找算法。例如下面的类,它以成员函数的形式重载了一个操作符函数:

class ACEClass

{

public:

ACEClass operator %(const ACEClass &) const;  //二元取余操作符

ACEClass memFunc1(const ACEClass &);

void memFunc2();

//.......

};

 

可以采用中缀或函数调用语法来调用这个重载的操作符函数:

ACEClass aa, ab, ac;

aa = ab % ac;             //采用中缀语法调用成员操作符%

aa = ab.operator%(ac);  //成员函数调用语法

aa = ab.memFunc1(ac);   //另一个成员函数调用

当我们使用函数调用语法时,应用的是普通的函数查找规则,即对ab.operator%(ac)调用的处理方式与memFunc1的相同。而对于中缀操作符调用来说,编译器不仅会考虑成员操作符,也会考虑非成员操作符:

ACEClass operator %(const ACEClass &, int ); //非成员操作符

//.........

void ACEClass::memFunc2()

{

*this % 12;              //调用非成员操作符%

operator %(*this, 12); //错误,实参太多

}

 

对于中缀操作符调用来说,编译器不仅会考虑成员操作符,也会考虑非成员操作符,上面代码中第一个对operator%的中缀调用,将会匹配非成员的那一个。注意:这不是函数重载的实例,而是编译器在两个不同地方查找候选函数。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值