为什么iostream定义了abs函数,我该如何阻止它呢?

Mik*_*ike 9 c++ gcc

以下c ++代码无法编译:

int main() {
  double a = abs(5.1);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

abs当然,它抱怨没有定义.但以下编译:

#include <iostream>

int main() {
  std::cout << abs(5.1) << std::endl;
  std::cout << abs(-5.1) << std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

它输出两个5(不是5.1).由于很多原因,这很糟糕.首先,abs我是一直使用它的这种自然而常见的功能,但这int部分几乎不是我想要的.其次,对我(或使用我的代码的人)来说,只是编写abs而不是注意它编译但做错了事情太容易了,因为我(他们)非常擅长忽略警告.第三,我只是简单地不明白为什么iostream abs无论如何都要定义一个函数.第四,我真的不明白为什么它会进入全局命名空间.

有什么办法可以阻止这个令人反感的abs函数进入我的全局命名空间吗?

如果重要,我正在使用

gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.6)
Run Code Online (Sandbox Code Playgroud)

Mar*_*k B 11

最有可能iostream包括stdlib.h做一些工作.这是宣告头部的C版本absint全局命名空间中唯一的(在C你不得不使用fabsdouble值).

我不知道有任何具体的方式,让abs被列入这样,但我知道,G ++ 4.5是多少,在没有通过基本带来多余的东西包括像更好的iostreamstring.

也可能会得到一个警告,即double被截断为int(编辑:是的,用于-Wconversion警告).

  • @Mike:当你说"这种事情让我烦恼"时,你的意思是它让你觉得无视警告导致错误的代码,对吧?;-p (2认同)

Jer*_*fin 5

在 C 中,不允许包含一个标准标头,就像包含任何其他标准标头一样。这避免了您所看到的问题,但在实施过程中付出了相当大的代价。

C++ 允许任何标准头包含任何其他标准头。这使得实现变得相当容易,但可能会导致您所看到的那种问题,其中包含看似不相关的标头使您实际上不想使用的函数可见,而不是因为该函数而出现错误你使用的根本没有声明。

不幸的是,我认为没有简单的方法来处理这个问题。尽管很容易想象<iostream>独立于<stdlib.h>,但更容易看出它如何需要/想要诸如 之类的东西的定义ios_base。定义禁止前者同时允许后者的事情需要相当多的额外工作。

然而,我应该指出,随着时间的推移,这种情况似乎确实有了很大改善。十年前,通过包含其中的几乎任何一个来获取几乎所有标准标头是相当常见的。尽管大多数仍然至少包含一些不是严格要求的内容,但它们通常更接近于仅定义所需的内容。