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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何同时拥有转换构造函数和转换运算符?相关的知识,希望对你有一定的参考价值。

考虑一下这个简单的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; }

请记住,它会阻止对隐式转换使用这些函数。

以上是关于如何同时拥有转换构造函数和转换运算符?的主要内容,如果未能解决你的问题,请参考以下文章

10个JavaScript代码片段,使你更加容易前端开发。

10个JavaScript代码片段,使你更加容易前端开发。

类中移动构造函数的位置/顺序很重要?与移动构造函数结合使用的模板化强制转换运算符

防止在构造函数中进行不希望的转换

为啥我的显式构造函数会为我的转换运算符创建这种歧义?

如何正确使用转换构造函数?