2009-07-16 94 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上,它工作得很好。我不知道这是参数相关查找的一个破坏的实现,其中参数的命名空间被意外地引入了吗?