重载运算符或数字转换的问题
Troubles with overloading operator or numbers conversion
我正在学习C++中的重载运算符,但我遇到了一个问题。
我写了一个(基元(类来表示 c++ 中的分数,以及一个函数来乘以其中的两个。
如果我想使用函数将分数乘以整数,一切都运行良好(感谢转换构造函数 :P(。 但是现在我想将分数乘以重载 *,就像两个数字一样。乘法first_fraction * second_fraction
效果很好,但编译器不想在fraction * 2
中将数字转换为分数。(它给出了此错误:错误 C2666:"运算符 *":2 个重载具有类似的转换(
如果我手动转换它,使用 fraction*static_cast<CFraction>(2)
它会再次工作。
谁能解释我做坏了什么?以下是完整代码:
#include <iostream>
using namespace std;
class CFraction
{
private:
int m_numerator;
int m_denominator;
public:
// Normal constructor, default constructor and conversion constructor
CFraction(int numerator=0,int denominator = 1) : m_numerator(numerator), m_denominator(denominator)
{
}
int numerator() const { return m_numerator; }
void numerator(int numerator) { m_numerator = numerator; }
int denominator() const { return m_denominator; }
void denominator(int denominator) { m_denominator = denominator; }
// Conversion to decimal form
operator float()
{
return m_numerator / static_cast<float>(m_denominator);
}
};
// Function to multiply 2 fractions
CFraction multiplication(const CFraction& f1,const CFraction& f2)
{
return CFraction(f1.numerator()*f2.numerator(),f1.denominator()*f2.denominator());
}
// Overloaded opearator to multiply 2 fractions
CFraction operator *(const CFraction& f1,const CFraction& f2)
{
return CFraction(f1.numerator()*f2.numerator(),f1.denominator()*f2.denominator());
}
int main()
{
CFraction fraction1(3,4);
cout << "Fraction: "<< fraction1.numerator() << "/" << fraction1.denominator() << endl;
cout << "Decimal: " << static_cast<float>(fraction1) << endl;
// Multiplication by function works very well
CFraction result = multiplication(fraction1,2);
// (ERROR) Compiller won't convert 2 to CFraction class
CFraction result1 = fraction1*2;
// Using manually covnerted integer - works again
CFraction result2 = fraction1*static_cast<CFraction>(2);
cout << "Multiplied by 2: " << static_cast<float>(result);
getchar();
return 0;
}
附言。如果重要的话,我正在使用MS Visual C+++ 2010
问题是你的类Fraction
有一个构造函数,它没有声明为explicit
,并且可以接受一个类型 int
的参数。因此,编译器可以选择此构造函数,以便在每次需要Fraction
时实现隐式用户定义的转换序列,但提供了int
。
此外,您的类型Fraction
还有一个转换运算符来float
,这使得每次需要float
时都可以将Fraction
隐式转换为float
,但提供了Fraction
。
因此,以下说明是模棱两可的:
CFraction result1 = fraction1*2;
编译器不知道是为 Fraction
类型的对象选择重载 operator *
并使用传递2
Fraction
的构造函数将第二个参数 ( 2
( 转换为Fraction
,或者更确切地说,是通过转换运算符将第一个参数转换为float
,然后使用内置operator *
执行float
和CC_之间的乘法24 .
在 C++11 中,您可以决定将转换运算符设为explicit
,这将防止歧义:您将无法再静默地将fraction1
转换为 2
,因此编译器将只能选择将2
转换为Fraction
并调用您的重载operator *
。
在这种情况下,如果要执行从 Fraction
到 float
的转换,则必须显式写入强制转换:
float f = static_cast<float>(result1);
另一种方法是使构造函数explicit
而不是转换运算符,以便在提供可转换为整数的单个值时编译器无法以静默方式实例化Fraction
。
这将解决上述乘法本身的歧义,因为它使编译器只能选择通过转换运算符将fraction1
转换为float
。但是,会出现两个问题。
首先,您将无法再编写:
CFraction result = multiplication(fraction1, 2);
因为这试图从第二个参数2
创建一个Fraction
(multiplication()
期望两个Fractions
作为其参数(。相反,您必须显式构造对象:
CFraction result = multiplication(fraction1, CFraction(2));
其次,即使上面的原始乘法有效,result1
的最终复制初始化也不会,因为(再次(这将需要隐式转换。
因此,您必须将复制初始化重写为:
CFraction result1 = CFraction(fraction1*2);
或者作为直接初始化:
CFraction result1(fraction1*2);
CFraction result2 = fraction1 * 2;
如何使用结果不会影响结果的计算方式,因此这只是:
fraction1 * 2
这是模棱两可的。您可以将fraction1
转换为浮点数并将其乘以 2。您可以将2
转换为Fraction
,然后使用 operator*
。编译器不知道你想要哪个。
由于您在 CFraction 类中提供了浮点数转换,因此编译器可以选择转换
CFraction result1 = fraction1*2;
将您自己的运算符 * 与 CFractions 一起使用,或将标准运算符 * 与浮点数和 int 一起使用。
如果您可以使用 C++11,则可以使用显式标记浮动转换。否则,请将其重命名为"as_float"。隐式转换通常是有问题的,最好避免。
尝试使用模板并将转换留给编译器。
- C++转换参数初始化问题
- 将父类对象强制转换为子类的问题
- 模板类转换问题 - 无法推断调用的函数
- 将旧管道转换为现代 openGL 时出现问题
- 将字节数组转换为带有字节序问题的指针
- 复制构造函数隐式转换问题
- 使用转换器提升 Python 问题 - 静态链接
- 与模板 (c++) 相关的转换问题
- 将文件复制到自定义位置,存在字符串转换问题
- 从基指针到派生的强制转换问题
- JNI 日期值转换问题,在C++中获取不同的长整型值
- 从 argv[1] 转换为字符 * 字符串后有什么问题?
- 将字符数组转换为结构时出现问题. 结构的字符数组变量溢出
- PX 转换例程编译问题
- 类型转换问题
- C++,遇到将双精度转换为整数的问题
- 拆分 pybind11 模块和自动类型转换问题
- 类型转换问题:返回为整数而不是浮点/类型
- Unicode 字符问题/转换参数
- c++和OpenCV:问题转换图像到灰度