Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么我的日志位于std名称空间中?_C++_Namespaces_Overloading - Fatal编程技术网

C++ 为什么我的日志位于std名称空间中?

C++ 为什么我的日志位于std名称空间中?,c++,namespaces,overloading,C++,Namespaces,Overloading,在下面的代码中,我定义了一个普通的log函数。在main中,我尽量不调用它;我调用std::log。然而,我自己的log被调用;我在屏幕上看到“日志”。有人知道为什么吗?我使用G++4.7和clang++3.2 #include <iostream> #include <cmath> double log(const double x) { std::cout << "log!\n"; return x; } int main(int argc, char

在下面的代码中,我定义了一个普通的
log
函数。在
main
中,我尽量不调用它;我调用
std::log
。然而,我自己的
log
被调用;我在屏幕上看到“日志”。有人知道为什么吗?我使用G++4.7和clang++3.2

#include <iostream>
#include <cmath>

double log(const double x) { std::cout << "log!\n"; return x; }

int main(int argc, char *argv[])
{
  std::log(3.14);
  return 0;
}
#包括
#包括

双对数(常数双x){std::cout我想发生的是,
std::log
只是委托给
::log
。不幸的是,
::log
只提供了一个
float
重载,而您可以提供一个
double
重载,使您的重载更加匹配。但我仍然不知道它在重载集中是如何被考虑的。

在libstdc++的
cmath
上,您将看到以下内容:

using ::log;
因此,它将全局名称空间中的math.h函数引入到
std
。不幸的是,您正在为
双日志(double)
提供一个实现,因此链接器将不会使用math库中的函数。因此libstdc++中肯定存在一个bug

编辑:我声称这是libstdc++中的一个bug,因为当您明确要求使用
std::
版本时,
std::log
不应该受到C库的干扰。当然,这种覆盖标准库函数的方法是C语言的一个老“特性”


编辑2:我发现该标准实际上并不禁止将全局名称空间中的名称带入
std
。因此,这毕竟不是一个bug,只是实现细节的结果。

C++标准17.6.1.2第4段(重点):

除了第18至30条和附录D中所指出的,每个标题<代码> cNe>代码>与相应的标题<代码>名称> h <代码>相同,如C标准库(1.2)或C++ unicode TR中所规定的,如包含的内容。(在C中定义为宏的名称除外)位于命名空间

std
的命名空间范围(3.3.6)内。未指定这些名称是否首先在全局命名空间范围内声明,然后通过显式使用声明(7.3.3)注入命名空间
std

G+++是这样的,所以可以将某些头文件重新用于C和C++。因此,G+允许在全局命名空间中声明和定义<代码>双日志(double)< /C> > 第17.6.4.3.3节第3段和第4段:

使用外部链接声明的标准C库中的每个名称都保留给实现,以便在命名空间
std
和全局命名空间中用作带有
extern“C”
链接的名称

使用外部链接声明的标准C库中的每个函数签名保留给实现,以用作
extern“C”
extern“C++”链接的函数签名,或用作全局命名空间中命名空间范围的名称

在第17.6.4.3节第2段的顶部:

如果程序在保留名称的上下文中声明或定义名称,而不是本子句明确允许的名称,则其行为是未定义的

另一方面,您不能以任何方式声明或定义
::log


工具链没有给你任何错误消息,但是.C++中的

< p>,编译器可以在全局命名空间中实现C库并委派给它(这是实现定义)。 17.6.1.2.4除非第18条至第30条和附录D中另有说明,否则每个标题cname的内容应相同 与C标准库(1.2)或C Unicode中规定的相应标题名.h相同 TR,如适当,如包含。在C++标准库中,声明除外(除了 C)中定义为宏的名称在名称空间标准的名称空间范围(3.3.6)内。 未指定这些名称是否首先在全局名称空间范围内声明,然后注入 通过显式使用声明(7.3.3)导入命名空间std

一般来说,我避免使用与C标准库相同的签名来创建函数。C++标准当然会给编译器提供使用这些签名的自由,如果选择的话,这意味着如果你尝试使用相同的签名,你可能会与编译器抗争。因此,你得到了奇怪的结果。 不过,我预计会出现链接器错误或警告,我认为这可能值得报告

[编辑]


哇,ninja'd.

因为您已经在全局名称空间中重写了它。如果您不想使用更安全、更干净的语言,例如,使用名称空间可以避免这种危险

:


听起来像是一个严重的编译器错误…我可以在Macports下的g++4.6上重现这个错误。但在g++4.2或4.4中不会发生这种情况。从这两种情况来看,我会说std::log()函数调用log()。但它会生成一个错误/警告,指出您的文件重新定义了日志或类似的内容。这很有趣。我甚至可以在ideone上复制它……我想自己知道答案。@ColeJohnson:这就是为什么您使用名称空间。并非所有内容都需要在一个类中。就我个人而言,我将所有内容都放在名称空间中,除了
main
.
需要提供
log(double)
。我在MSVC10上也期望得到同样的结果,我最终在链接上得到了一个重复的符号错误,但只是在3到4次重建之后。@aschepper:
需要提供
double std::log(double)
(我把重点放在名称空间上是一件大事,因为现在正是如此)。该标准要求它们位于
::std
命名空间中,如果它们选择,每个实现都可以在全局命名空间中自由定义它们。@DeadMG:你不是说
::log
(C库函数)提供了一个
p
#include <iostream>
#include <cmath>  // Uses ::log, which would be the log() here if it were not in a namespace, see http://stackoverflow.com/questions/11892976/why-is-my-log-in-the-std-namespace

// Silently overrides std::log
//double log(double d) { return 420; }

namespace uniquename {
    using namespace std;  // So we don't have to waste space on std:: when not needed.

    double log(double d) {
        return 42;
    }

    int main() {
        cout << "Our log: " << log(4.2) << endl;
        cout << "Standard log: " << std::log(4.2);
        return 0;
    }
}

// Global wrapper for our contained code.
int main() {
    return uniquename::main();
}
Our log: 42
Standard log: 1.43508