不明确的过载调用abs(双)

56 c++ std cmath

我有以下C++代码:

#include <math.h>
#include <cmath.h>      // per http://www.cplusplus.com/reference/clibrary/cmath/abs/

// snip ...

if ( (loan_balance < 0) && (abs(loan_balance) > loan_payment) ) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

make爆炸:

error: call of overloaded 'abs(double)' is ambiguous
Run Code Online (Sandbox Code Playgroud)

也感兴趣:

/usr/include/stdlib.h:785: note: candidates are: int abs(int)
Run Code Online (Sandbox Code Playgroud)

如何指定编译器需要在cmath.h中调用可以处理浮点数的abs()?

编译器信息(不确定这是否重要):

[some_man@some_box ~/some_code]#  gcc -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr    /share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=i386-redhat-linux
Thread model: posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-44)
Run Code Online (Sandbox Code Playgroud)

sbi*_*sbi 48

标头<math.h>是C std lib标头.它在全局命名空间中定义了很多东西.标头<cmath>是该标头的C++版本.它在命名空间中定义了基本相同的东西std.(有一些差异,比如C++版本带有一些函数的重载,但这并不重要.)标题<cmath.h>不存在.

由于供应商不想维护基本相同标题的两个版本,因此他们想出了在幕后只有一个版本的不同可能性.通常,这是C头(因为C++编译器能够解析它,而相反的方法不起作用),并且C++头只包含它并将所有内容拉入命名空间std.或者有一些宏观魔法用于解析相同的标题,无论是否namespace std包裹它.对此添加,在某些环境中,如果标头没有文件扩展名(如编辑器无法突出显示代码等),则会很麻烦.因此,一些供应商将<cmath>是一个单行,包括一些带有.h扩展名的其他标题.或一些将映射所有包括匹配<cblah><blah.h>(其通过宏魔法,成为C++头时__cplusplus被定义,否则成为C报头)或<cblah.h>或任何.

这就是为什么在某些平台上,包括那些<cmath.h>不应该存在的平台,最初会成功的,尽管它可能会使编译器在以后出现故障.

我不知道你使用哪个std lib实现.我想这是GCC附带的那个,但我不知道,所以我无法解释你的情况究竟发生了什么.但它肯定是上述特定于供应商的黑客之一,你包括一个你不应该自己包含的标题.也许它是<cmath>映射到<cmath.h>一个你没有定义的特定(一组)宏的那个,所以你最终得到了这两个定义.

但请注意,此代码仍不应编译:

#include <cmath>

double f(double d)
{
  return abs(d);
}
Run Code Online (Sandbox Code Playgroud)

abs()全局命名空间中不应该有一个(它是std::abs()).然而,根据上述实施技巧,可能存在.稍后移植这样的代码(或者只是尝试用你的供应商的下一个版本编译它不允许这样做)可能非常繁琐,所以你应该留意这一点.


小智 38

它归结为:math.h来自C于10年前的创建.在math.h中,由于其原始性质,该abs()函数"基本上"仅适用于整数类型,如果您想获得double的绝对值,则必须使用fabs().当C++被创建时,它就math.h完成了它cmath.cmath本质上是math.h,但对C++进行了改进.它改进了诸如必须区分fabs()和abs之类的东西,并且仅abs()针对双精度和整数类型进行了改进.总结一下:使用math.h并使用abs()整数,fabs()双精度或使用cmath,只需要abs就可以了(更容易和推荐)

希望这可以帮助任何有同样问题的人!


Nia*_*ang 17

使用fabs()而不是abs(),它是相同的,但对于浮点数而不是整数.

  • 这在`std`命名空间中并不是很准确,其中`abs`是`float`,`double`等的重载. (6认同)