2009-07-16 95 views
7

我不明白爲什麼這段代碼不能編譯:命名空間衝突在C++

namespace A { 
     class F {};    // line 2 
     class H : public F {}; 
} 

namespace B { 
     void F(A::H x);   // line 7 
     void G(A::H x) { 
       F(x);   // line 9 
     } 
} 

我使用gcc 4.3.3,錯誤是:

s3.cpp: In function ‘void B::G(A::H)’: 
s3.cpp:2: error: ‘class A::F’ is not a function, 
s3.cpp:7: error: conflict with ‘void B::F(A::H)’ 
s3.cpp:9: error: in call to ‘F’ 

我認爲這是因爲在第9行沒有名稱空間前綴,F(x)應該明確表示只有B::F(x)。編譯器試圖將x轉換成它自己的超類。根據我的理解,它不應該。它爲什麼這樣做?

回答

11

這是因爲編譯器會在同一個命名空間中搜索函數的參數。編譯器發現有A::F標識符,但它不是一個函數。結果你會得到錯誤。

據我記憶,這是標準行爲。

3.4.2參數依賴性名稱查找 當不合格的名稱被用作一個函數調用(5.2.2)的後綴表達式,其它的命名空間通常的不合格查找(3.4時不考慮。 1)可以被搜索,並且可以找到不可見的命名空間範圍的朋友函數聲明(11.4)。這些對搜索的修改取決於參數的類型(以及模板參數,模板參數的名稱空間)。

對於函數調用中的每個參數類型T,都有一組零個或多個關聯的名稱空間以及一組零個或多個要考慮的關聯類。命名空間和類的集合完全由函數參數的類型(以及任何模板模板參數的命名空間)決定。 用於指定類型的Typedef名稱和using-declarations不參與此集合。通過以下方式確定命名空間和類的集合...

此規則允許你寫下面的代碼:

std::vector<int> x; 
// adding some data to x 
//... 

// now sort it 
sort(x.begin(), x.end()); // no need to write std::sort 

最後:由於Core Issue 218一些編譯器會編譯有問題的代碼沒有任何錯誤。

+1

所謂的Koenig查找,實際上在3.4節中描述。2的C++標準。 – 2009-07-16 17:43:36

+0

那麼如果VS編譯這個,這是一個錯誤? – liori 2009-07-16 17:45:18

1

很奇怪,我複製並直接粘貼到VS 2005和我得到一個錯誤,這是我預料:

錯誤1個錯誤LNK2001:無法解析的外部符號「無效__cdecl B :: F(A類::^h )「

因爲我們還沒有在命名空間B中實際定義F(x)......不知道爲什麼Gcc會給出這個錯誤。

0

我只是試圖編譯它在Visual Studio 2005上,它工作得很好。我不知道這是參數相關查找的一個破壞的實現,其中參數的命名空間被意外地引入了嗎?