如何同时拥有转换构造函数和转换运算符?

时间:2018-03-04 06:54:36

标签: c++ type-conversion operator-overloading

考虑这个简单的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。如果要进行两次转换并且仍然编译程序,我该怎么办?

2 个答案:

答案 0 :(得分:2)

从错误中,编译器抱怨,因为它无法自行解决歧义。正确指出有两种可能的解决方案,如果没有您的额外见解,它不知道选择哪一种。

您希望评估(f1 + 2),如果您想要添加分数,建议您将来电者更改为(f1 + Fraction(2))

如果您想要重复添加,请将其更改为(double(f1)+2)

最重要的是,您可以继续将分数转换为分数和分数。整数到分数构造,但是当编译器存在歧义时,您需要显式指定所需的行为。

答案 1 :(得分:1)

制作一个或两个转换函数explicit。这将阻止友好编译器在基于隐式转换序列选择运算符+的重载时隐式使用它们。

explicit Fraction(int nn): nom(nn), den(1) { }
explicit operator double() const { return double(nom) / den; }

请记住,它会阻止所有使用这些函数进行隐式转换。