考虑一下这个简单的C ++ - 17程序:
#include <iostream>
#include <math.h>
using namespace std;
class Fraction {
public:
int nom;
int den;
Fraction operator+ (const Fraction& other) {
int nn = nom * other.den +
den * other.nom;
int dd = den * other.den;
return Fraction(nn, dd);
}
Fraction(int nn, int dn): nom(nn), den(dn) { }
Fraction(int nn): nom(nn), den(1) { }
operator double() const { return double(nom) / den; }
};
ostream& operator<<(ostream& os, const Fraction& frac) {
return os << frac.nom << '/' << frac.den;
}
int main() {
Fraction f1(1, 4);
cout << "f1 = " << f1 << endl << "f1+2 = " << (f1 + 2) << endl;
return 0;
}
该程序产生编译错误:
main.cpp:35:52: error: use of overloaded operator '+' is ambiguous (with operand types 'Fraction' and 'int')
cout << "f1 = " << f1 << endl << "f1+2 = " << (f1 + 2) << endl;
~~ ^ ~
main.cpp:17:11: note: candidate function
Fraction operator+ (const Fraction& other) {
^
main.cpp:35:52: note: built-in candidate operator+(double, int)
cout << "f1 = " << f1 << endl << "f1+2 = " << (f1 + 2) << endl;
^
但是,如果我删除转换构造函数“Fraction(int nn):nom(nn),den(1){}”或转换运算符“operator double()const {return double(nom)/ den;}”,程序运行正常。
我想要转换为Fraction和来自Fraction。我可以做些什么来进行两次转换并且仍然可以编译程序?
从错误中,编译器抱怨,因为它无法自行解决歧义。正确指出有两种可能的解决方案,如果没有您的额外见解,它不知道选择哪一种。
您如何评价(f1 + 2)
,如果您想要分数添加,建议将来电者更改为(f1 + Fraction(2))
。
如果您想要加倍,请将其更改为(double(f1)+2)
。
最重要的是,您可以继续从分数到双精度和整数到分数构造的转换,但是当编译器存在歧义时,您需要明确指定所需的行为。
制作一个或两个转换函数explicit
。这将阻止您的友好编译器在基于隐式转换序列选择运算符+
的重载时隐式使用它们。
explicit Fraction(int nn): nom(nn), den(1) { }
explicit operator double() const { return double(nom) / den; }
请记住,它会阻止对隐式转换使用这些函数。