我无法理解为什么这段代码无法编译:
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
强制转换为自己的超类。根据我的理解,它不应该。为什么这样做?
答案 0 :(得分: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 :(得分:4)
您是否尝试过使用其他编译器?这里有gcc bug report暂停(无论这意味着什么)。
编辑:经过一些研究,我发现了more official bug。答案 2 :(得分:1)
很奇怪,我直接复制并粘贴到VS 2005,我收到了一个错误,我预料到:
错误1错误LNK2001:未解析的外部符号“void __cdecl B :: F(A类:: H)”
因为我们实际上没有在命名空间B中定义F(x)...不确定为什么Gcc会给出这个错误。
答案 3 :(得分:0)
我只是尝试在Visual Studio 2005上编译它并且它工作正常。我想知道它是否是Argument Dependent Lookup的破坏实现,其中参数的命名空间被意外引入?