C++在命名空间中声明与全局命名空间中的函数同名的函数

C++ Declaring function in namespace with same name as function in global namespace

本文关键字:函数 命名空间 声明 C++ 全局      更新时间:2023-10-16

我有一个关于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++过于简单。