【问题标题】:How can I have both conversion constructor and conversion operator?如何同时拥有转换构造函数和转换运算符?
【发布时间】:2018-08-12 01:34:53
【问题描述】:

考虑这个简单的 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; }”,程序运行良好。

我想在分数之间进行转换。我该怎么做才能进行两种转换并且仍然可以编译程序?

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      底线,您可以继续进行从分数到双精度和整数到分数构造的转换,但是当编译器存在歧义时,您需要明确指定您想要的行为。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-25
        • 1970-01-01
        • 2020-06-12
        • 2021-12-04
        • 2014-02-17
        • 1970-01-01
        • 2012-09-02
        • 1970-01-01
        相关资源
        最近更新 更多