C++必知必会之(25)实参相依的查找

原创 2013年12月04日 10:27:37

1、实参相依的查找ADL:

当查找一个函数调用表达式中的函数名字时,编译器也会到“包含函数调用实参的类型”的名字空间中检查。

例如:

namespace org_semantics  {

      class X  { .... };

       void f ( const X & );

       void g ( X * );

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

       class String {   ....   };

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

}

//.....

int g ( org_semantics::X * );

void aFunc( )   {

     org_semantics::X  a;

     f ( a);                  //调用org_semantics::f

     g ( a);                //错误,调用具有歧义

     a = a + a;            //调用org_semantics::operator+

}

普通的查找是不会发现函数org_semantics::f的,因为它被嵌套在一个名字空间内,并且对f的使用需要以该名字空间的名字加以限定。

然而,由于实参a的类型被定义于org_semantics名字空间中,因此,编译器也会到该名字空间中检查候选函数。


本例中,程序员本来以为编译器会发现全局的g,但由于实参的类型是org_sematics::X *,因此该名字空间内的g成了候选函数之一,从而导致这个调用有歧义。

即使对g的调用导致了两个候选函数参与重载解析,::g实际上也并未重载org_sematics::g,因为它们不是声明于同一个作用域中的(参考重载与重写并不同)。

ADL是关于函数如何被调用的一个属性,而重载是关于函数被如何声明的一个属性。


2、可以看到ADL在对重载操作符的中缀调用中发挥作用,例如在aFunc中对operator + 的调用。

在这里,中缀表达式a+a等价于operator+( a,a),ADL将会在org_sematics名字空间中发现重载的operator+。


3、实际上,好多人广泛地应用了ADL但没意识到这点。考虑如下对<iostream>的常见使用:

org_sematics::String name( " Qwan" );

std::cout<<" Hello"<<name;

本例中,对operator<<的第一个使用(即最左边那一个),极有可能调用的是类模版std::basic_ostream的一个成员函数,而第二个则是对位于org_semantics名字空间中重载的operator<<的非成员函数的调用。ADL自动的打理了这些。

相关文章推荐

C++必知必会 - 成员函数查找

调用一个成员函数,涉及三个步骤:第一步,编译器查找函数的名字;第二步,从可用候选者中选择最佳匹配函数;第三步,检查是否具有访问该匹配函数的权限。一旦在内层作用域中找到匹配的,编译器就不会到外层作用域中...
  • fishhg
  • fishhg
  • 2011年05月03日 22:28
  • 637

C++必知必会之(24)成员函数查找

1、调用一个成员函数时,包括三个步骤: 第一步,编译器查找函数的名字; 第二步,从可用候选者中选择最佳匹配函数; 第三步,检查是否具有访问该匹配函数的权限。 2、很多与函数匹配有关的错误并非源于对...

C++必知必会之(26)操作符函数查找

有时看上去

C++必知必会之(6)数组形参

1、C++中根本不存在所谓的“数组形参”,因为在数组传入时,实质上只传入指向其首元素的指针。 void average( int ary[12] );   //形参ary是一个int * //.......

C++必知必会之(17)处理函数和数组声明

1、指向函数的指针声明与指向数组的指针声明很容易混淆, 主要原因在于函数和数组修饰符的优先级比指针修饰符的优先级高,因此通常需要使用圆括号。 int *f1( );     //一个返回值为int *...

c++必知必会-2

2、多态。多态类型就是带有虚函数的类类型。多态对象则是不仅有一种类型的对象,而“多态基类”则是一个为满足多态对象的使用需求而设计的基类。 一个多态类型,从基类继承的最重要的东西就是它们的接口,而不是...
  • ljp1919
  • ljp1919
  • 2013年02月24日 14:54
  • 335

C++必知必会之(30)Factory Method模式

一个高级设计通常要求基于一个现有对象类型来创建一个“适当”类型的对象。 例如:我们可能拥有一个指向某种类型的Employee对象的指针或引用,现在需要...

C++必知必会之(13)复制操作

1、复制构造和复制赋值是两种不同的操作。它们一般被放到一起,同时出现,并且必须兼容: class Impl; class Handle  {     public:         //.....  ...

C++必知必会 - placement new

"placement new"? 它到底是什么?placement new 是重载operator new的一个标准、全局的版本,它不能被自定义的版本代替(不像普通的operator new和oper...
  • fishhg
  • fishhg
  • 2011年05月04日 22:57
  • 180

C++必知必会之(22)Template Method模式

1、Template Method模式(模版方法)模式和C++模版一点关系都没有。 前者是基类设计者为派生类设计者提供清晰指示的一种方式,这个指示就是“应该如何实现基类所规定的契约”。 基类可以自...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++必知必会之(25)实参相依的查找
举报原因:
原因补充:

(最多只允许输入30个字)