我对C ++中的函数声明范围有疑问。假设使用#include <cmath>
将函数符号引入全局命名空间。根据我的理解,原则上它只应该在std
命名空间中引入符号,但实际上,根据我自己的经验,一些符号出现在全局命名空间中。这个答案似乎证实了这一点:cmath header confusion。
现在,当我在namespace foo { }
内声明一个函数(与全局命名空间中的函数具有相同的原型)时会发生什么?例如,假设来自sqrt()
的{{1}}最终在全局命名空间中,我有:
<cmath>
模板被解析为符号#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 );
}
,它似乎应该与全局命名空间中的模板冲突。它似乎有用,但这通常是一种不好的做法吗?
更一般地说,在同一名称空间内使用时,在名称空间内声明的函数是否优先于全局函数?这是否以任何方式违反了C ++标准?
答案 0 :(得分:3)
这里有两个不同的问题。
首先,拉入某些标头确实会在全局命名空间和std
命名空间中注入符号。这种香肠制作与C ++的遗产和根源有关;并尝试尽可能少地在C ++中编译遗留的C代码。
其次,确实......
在命名空间内声明的函数优先于全局 函数,当从同一名称空间内使用时?
这是正确的。而且,不,这不是
以任何方式违反C ++标准?
事实上,C ++标准明确指出这是事情应该如何运作。从名称空间解析引用首先搜索相同的名称空间,作为第一个业务顺序。然后是父命名空间,如果是嵌套命名空间。然后,最终,全局命名空间。
然后,using namespace
使事情复杂化。这就是为什么you should not do that。
最后,为了让事情变得有趣,还有argument dependent lookup通过搜索不在当前命名空间,父命名空间或全局命名空间中的函数来将所有这些规则放在头上,但在与函数参数相同的命名空间。
没有人指责C ++是简单的。