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

时间:2012-03-15 17:58:08

标签: c++ gcc

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

int main() {
  double a = abs(5.1);
  return 0;
}

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

#include <iostream>

int main() {
  std::cout << abs(5.1) << std::endl;
  std::cout << abs(-5.1) << std::endl;
  return 0;
}

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

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

如果重要,我正在使用

gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.6)

3 个答案:

答案 0 :(得分:11)

最有可能iostream包括stdlib.h来完成其部分工作。这是标头的C版本,仅在全局命名空间中为abs声明int(在C中,您必须使用fabs来表示double值。

我不知道有任何具体方法可以让abs不被包含在内,但我知道g ++ 4.5 很多更好的是没有基本带来的多余东西包括iostreamstring

也可能会收到一条警告,指出double被截断为int(编辑:是的,使用-Wconversion来警告)。

答案 1 :(得分:4)

在C中,包括一个标准标题是允许其行为,因为它包含任何其他标准标题。这样可以避免您遇到的问题,而且难以实施。

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

不幸的是,我认为没有一种简单的方法可以解决这个问题。虽然很容易想象<iostream>独立于<stdlib.h>,但更容易看出它可能需要/想要ios_base之类的定义。在允许后者的同时定义禁止前者的事情还需要相当多的额外工作。

但是,我应该提一下,随着时间的推移,这种情况似乎确实有所改善。十年前,几乎所有标准标题都包含在几乎所有标准标题中是相当普遍的。虽然大多数仍然包括至少一些并非严格要求,但它们通常更接近于每个仅定义它所需要的内容。

答案 2 :(得分:1)

如果这是一个持续的维护问题,为什么不在程序开头添加一些专门检查abs()问题的代码?

// test if abs() is defined incorrectly, as would happen if <stdlib.h> were
// included by <iostream>.  abs() it should return a float/double, not an int
// (put suggestions here how to fix problem)
if (abs(-5.1) == 5)
{
     std::cerr << "Invalid build:  abs() defined improperly, ..." << std::endl;
     return 2;  // exit program by returning from main
}

这将使警告被忽视更加困难。