我有一个关于C++中函数声明作用域的问题。假设使用#include <cmath>
将一个函数符号引入全局名称空间。根据我的理解,原则上它应该只将符号引入std
命名空间,但在实践中,根据我自己的经验,一些符号出现在全局命名空间中。这个答案似乎证实了这一点:cmath标头混淆。
现在,当我在namespace foo { }
中声明一个函数(与全局命名空间中的函数具有相同的原型)时,会发生什么?例如,假设<cmath>
中的sqrt()
最终在全局命名空间中,并且我有:
#include <cmath>
namespace foo {
template <class T>
T sqrt( T x ) {
// do something extra...
return std::sqrt( x );
}
}
// ...
void foo::bar() {
double a = 4.0;
double b = sqrt( a );
}
模板被解析为符号double sqrt( double x )
,这似乎应该与全局命名空间中的符号冲突。这似乎有效,但这通常是一种糟糕的做法吗?
更一般地说,当在同一命名空间内使用时,在命名空间内声明的函数是否优先于全局函数?这在任何方面都违反了C++标准吗?
这里有两个独立的问题。
首先,引入某些标头确实会在全局命名空间和std
命名空间中注入符号。这种香肠制作与C++在C中的传统和根源有关;并尝试有一个很好的机会让遗留的C代码在C++中可编译,而尽可能少的痛苦。
第二,确实。。。
在命名空间中声明的函数优先于全局函数,当在同一命名空间内使用时?
这是正确的。而且,不,这不是
以任何方式违反C++标准?
事实上,C++标准明确规定这就是工作方式。解析命名空间中的引用首先搜索与业务的第一顺序相同的命名空间。然后是父命名空间,如果是嵌套的命名空间。然后,最终是全局命名空间。
然后,using namespace
使事情变得复杂。这就是为什么你不应该那样做。
最后,为了让事情变得有趣,还有一种依赖于参数的查找,它通过搜索不在当前命名空间、父命名空间或全局命名空间中的函数,而是在与函数参数相同的命名空间中,来颠覆所有这些规则。
从来没有人指责C++过于简单。