2013-02-15 54 views
3

这很奇怪,我试图找到为什么第一次调用Draw的对象shape没有问题,而第二次调用“text”字段上的Draw只在提供名称空间的前缀时才起作用? (即Shapes::Draw):命名空间中的C++函数将不起作用?

#include <iostream> 
namespace Shapes 
{ 
    class Shape { 
     public: 
      Shape() {} 
      virtual void InnerDraw() const { 
       std::cout << "Shape\n"; 
      } 
    }; 

    class Square : public Shape { 
     public: 
      void InnerDraw() { std::cout << "Square\n"; } 
    }; 

    void Draw(char* text) { std::cout << text; } 

    void Draw(const Shape& shape) { 
     Draw("Inner: "); 
     shape.InnerDraw(); 
    } 

    Shape operator+(const Shape& shape1,const Shape& shape2){ 
     return Shape(); 
    } 
} 


int main() { 
    const Shapes::Square square; 
    Shapes::Shape shape(square); 

    Draw(shape); // No need for Shapes:: 
    Draw("test"); // Not working. Needs Shapes:: prefix 

    return 0; 
} 
+3

GoogleKönig-lookup - sorry,Koenig-lookup to be precise – Csq 2013-02-15 23:34:56

+1

[Argument Dependent Name Lookup](http://en.wikipedia.org/wiki/Argument-dependent_name_lookup) – hmjd 2013-02-15 23:36:16

+0

Oh,_that_ call。 – 2013-02-15 23:37:55

回答

3

对于Draw(shape)编译器会在shape S型的定义,看看是否有一个名为Draw匹配函数的命名空间。它找到它并称之为它。对于Draw("test"),没有参数的命名空间,所以无处可查。这称为参数相关查询,简称ADL。

+0

评论消失了。 'main'中没有看到两个调用。在“Draw”过载之一中完全误解了由于红鲱鱼引起的问题。有点醉了。 – 2013-02-15 23:38:55

+2

@LightnessRacesinOrbit - 出门开车。你无法编写代码。 '' – 2013-02-15 23:39:51

+1

@LightnessRacesinOrbit这次我们会原谅你。一饮而尽! – 2013-02-15 23:44:31

2

这叫做Argument-dependent lookup。当调用一个非限定函数时,编译器会为该函数的所有参数查询命名空间,并将所有匹配函数添加到该过载集中。所以当你说Draw(shape)它发现Shapes::Draw(const Shapes::Shape& shape)基于shape参数。但是当你说Draw("test")时,参数"test"没有名称空间,当然不是所需的Shapes::名称空间。

+1

如果在呼叫视线范围内发现_function_ ** **,ADL也适用。 ADL发现的函数被添加到过载集合中。 – 2013-02-15 23:38:00

+0

@CharlesBailey:好点。我会修改我的答案。 – 2013-02-15 23:42:13