2013-02-15 65 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