我有一个复数类,我正在尝试实现一个函数来计算模数(这需要使用sqrt)。
我的头文件如下:
#ifndef MY_CLASS_H
#define MY_CLASS_H
template <class T> class complex
{
// function to overload operator<< a friend
template <class T>
friend std::ostream& operator<< (std::ostream &os, const complex<T> &z);
private:
T re,im;
public:
// Constructors & destructor
complex(){re=im=0;}
complex( const T& r, const T& i ) : re(r), im(i) {}
~complex(){}
// Return real component
T realcomp() const {return re;}
// Return imaginary component
T imagcomp() const {return im;}
// Return modulus
double modulus() {return sqrt(im*im + re*re);}
etc....编译器输出错误:
error C2668: 'sqrt' : ambiguous call to overloaded function
could be 'long double sqrt(long double)'
or 'float sqrt(float)'
or 'double sqrt(double)'我知道这告诉我sqrt需要知道它传递的是什么类型的数据。
对于我的程序,im和re将接受double或int的值。
我说sqrt只接受浮点值,对吗?如果是这样,我该如何强制im和re使用浮点数,而不会出现“数据丢失”警告。我可以在不转换它们的情况下做到这一点吗?
发布于 2012-04-14 01:29:36
不,sqrt通常不接受浮点数。它需要什么取决于你的库。在您的例子中,有几个重载的sqrt函数,一个接受float,一个接受double,另一个接受long double。
问题是,它们都不接受int,而且有多个从int到您可以使用的类型的转换,所以编译器让您选择(通过强制转换)。如果您只使用double或int,则强制转换为double --不会丢失准确性。如果你想在某一时刻使用long double,那就转换成那样。
double modulus() {return sqrt((double)im*im + re*re);}发布于 2012-04-14 01:45:22
有几种解决方案,但首先,您的代码有一个问题:函数sqrt来自哪里。如果用户包含<sqrt.h>,那么您应该只获得double版本,并且没有歧义。如果用户包含<csqrt>,那么在之前的C++11中,代码应该找不到任何sqrt;实际上,没有任何编译器正确地实现了这一点,您得到的结果取决于实现。
最安全的解决方案是声明一个您自己的特殊名称空间,包括<csqrt>,在其中定义您需要的sqrt,在其实现中使用std::sqrt,并在您的名称空间中调用sqrt:
#include <csqrt>
namespace SafetyFirst
{
inline int
sqrt( int in )
{
return static_cast<int>( std::sqrt( static_cast<double>( in ) ) );
}
inline double
sqrt( double in )
{
return std::sqrt( in ) ;
}
// And so on for any other types you might need. The
// standard provides std::sqrt for the floating point
// types only.
}通过这种方式,重载解析将始终找到完全匹配的函数,并且您可以准确地确定您实际需要的函数。您还可以让客户端定义可能有用的新数字类型:它们只需在相同的名称空间中定义它们的sqrt,可能会转发到与该类型位于相同名称空间中的实现。
或者,您可以执行以下操作:
#include <cmath> // To ensure getting a fixed set of overloads
using std::sqrt;
inline int
sqrt( int in )
{
return static_cast<int>( std::sqrt( static_cast<double>( in ) ) );
}
// And so on for any standard integral types you want...
// And your class here...对于客户端定义的类型,ADL将确保编译器在正确的名称空间中查找,因此它们不必在您的名称空间中提供转发函数。
这实际上是一个相当好的解决方案,除了它可能会搞乱客户端代码,而不是期望在全局名称空间中找到std::sqrt( float )。(这样的代码是不可移植的,但它可能存在于某些平台上。)
发布于 2012-04-14 01:23:32
试试这个:
double modulus() {return sqrt((double)im*im + re*re);}您将总是以这种方式调用double sqrt(double),但是根据您的描述,这可能是可以的。
https://stackoverflow.com/questions/10145295
复制相似问题