C++ 如何解决不明确的运算符重载问题?

C++ 如何解决不明确的运算符重载问题?,c++,operator-overloading,C++,Operator Overloading,我有一个类分数定义为: class Fraction { int d_numerator; int d_denominator; Fraction(numerator, denominator) : d_numerator(numerator), d_denominator(denominator) {} Fraction(double number) : d_numerator(static_cast<int>(number * 10

我有一个类
分数
定义为:

class Fraction
{
  int d_numerator;
  int d_denominator;

  Fraction(numerator, denominator)
    :
  d_numerator(numerator), d_denominator(denominator)
  {}

  Fraction(double number)
    :
  d_numerator(static_cast<int>(number * 100000)), d_denominator(100000)
  {}
};
我有一个重载的
操作符(double)
函数,它允许我将
分数
对象强制转换为类型
double
,例如
double b=(double)a其中
a
属于
Fraction
类型

Fraction::operator(double){//omitted for brevity}
我希望能够像这样将一个
double
添加到
分数中:
分数c=a+2.6

问题是这不会编译,因为有几种方法可以解释语句
分数c=a+2.6的转换

我发现以下编译器错误:

错误C2666:“分数::运算符+”:3个重载具有类似的转换 可能是

  • '分数分数::运算符+(常数分数&)
  • 或内置C++操作符+(double,double)
  • 或内置C++操作符+(浮点,double)< /LI> 我认为其本质是,编译器应该:

  • 使用
    操作符(double)
    重载将
    分数a
    转换为双精度,并将两个双精度相加
  • 或者,使用允许此操作的构造函数将双精度2.6转换为
    分数
    ,然后添加两个
    分数
  • 有没有办法强迫编译器使用另一条路径中的一条,或者任由它选择其中一条。只要结果如预期,我不介意

    谢谢

    我希望能够给这样的分数加上一个双精度:
    分数c=a+2.6

    问题是这将不会编译,因为有几种解释语句转换的方法
    分数c=a+2.6

    您有一个隐式转换运算符(从
    Fraction
    double
    )和一个隐式转换构造函数(从
    double
    Fraction
    ),两者都会导致
    运算符+
    的有效匹配,并且编译器拒绝继续这种歧义

    建议进行
    显式转换
    ,但如果您确实希望
    分数c=a+2.6
    起作用,您可以满足于进行
    双显式转换。这意味着,如果您想将
    a
    转换为
    double
    ,则必须
    static\u cast(a)

    我制作了一个工作示例,用于在代码中添加两个带有注释的
    分数。用其他操作符扩展它只是一个练习

    #include <iostream>
    
    class Fraction {
    public:
        Fraction(int numerator, int denominator) :
            d_numerator(numerator), d_denominator(denominator) 
        {}
    
        // a converting constructor for double
        Fraction(double number) :
            d_numerator(static_cast<int>(number * 1000000)), d_denominator(1000000)
        {}
    
        // add a Fraction to *this
        Fraction& operator+=(const Fraction& o) {
            d_numerator = d_numerator * o.d_denominator + o.d_numerator * d_denominator;
            d_denominator *= o.d_denominator;
            return *this;
        }
    
        // explicit conversion to double
        explicit operator double() const {
            return static_cast<double>(d_numerator) / d_denominator;
        }
    
    private:
        int d_numerator;
        int d_denominator;
    };
    
    // A free function to add two Fractions - take the left hand side by value
    // and you can return the same object (after having added the right hand side to it).
    Fraction operator+(Fraction a, const Fraction& b) {
        // use the member operator+=
        return a += b;
    }
    
    #包括
    类分数{
    公众:
    分数(整数分子、整数分母):
    d_分子(分子),d_分母(分母)
    {}
    //double的转换构造函数
    分数(双数):
    d_分子(静态(数字*1000000)),d_分母(1000000)
    {}
    //在*上加一个分数
    分数和运算符+=(常数分数和o){
    d_分子=d_分子*o.d_分母+o.d_分子*d_分母;
    d_分母*=o.d_分母;
    归还*这个;
    }
    //显式转换为双精度
    显式运算符double()常量{
    返回静态(d_分子)/d_分母;
    }
    私人:
    int d_分子;
    int d_分母;
    };
    //添加两个分数的自由函数-按值取左侧
    //您可以返回相同的对象(在向其添加右侧之后)。
    分数运算符+(分数a、常数分数和b){
    //使用成员运算符+=
    返回a+=b;
    }
    

    在演示中,我使用了C++17函数,因为在处理分数时,数字越小越好,而且它还支持流式打印

    我希望能够给这样的分数加上一个双精度:
    分数c=a+2.6

    问题是这将不会编译,因为有几种解释语句转换的方法
    分数c=a+2.6

    您有一个隐式转换运算符(从
    Fraction
    double
    )和一个隐式转换构造函数(从
    double
    Fraction
    ),两者都会导致
    运算符+
    的有效匹配,并且编译器拒绝继续这种歧义

    建议进行
    显式转换
    ,但如果您确实希望
    分数c=a+2.6
    起作用,您可以满足于进行
    双显式转换。这意味着,如果您想将
    a
    转换为
    double
    ,则必须
    static\u cast(a)

    我制作了一个工作示例,用于在代码中添加两个带有注释的
    分数。用其他操作符扩展它只是一个练习

    #include <iostream>
    
    class Fraction {
    public:
        Fraction(int numerator, int denominator) :
            d_numerator(numerator), d_denominator(denominator) 
        {}
    
        // a converting constructor for double
        Fraction(double number) :
            d_numerator(static_cast<int>(number * 1000000)), d_denominator(1000000)
        {}
    
        // add a Fraction to *this
        Fraction& operator+=(const Fraction& o) {
            d_numerator = d_numerator * o.d_denominator + o.d_numerator * d_denominator;
            d_denominator *= o.d_denominator;
            return *this;
        }
    
        // explicit conversion to double
        explicit operator double() const {
            return static_cast<double>(d_numerator) / d_denominator;
        }
    
    private:
        int d_numerator;
        int d_denominator;
    };
    
    // A free function to add two Fractions - take the left hand side by value
    // and you can return the same object (after having added the right hand side to it).
    Fraction operator+(Fraction a, const Fraction& b) {
        // use the member operator+=
        return a += b;
    }
    
    #包括
    类分数{
    公众:
    分数(整数分子、整数分母):
    d_分子(分子),d_分母(分母)
    {}
    //double的转换构造函数
    分数(双数):
    d_分子(静态(数字*1000000)),d_分母(1000000)
    {}
    //在*上加一个分数
    分数和运算符+=(常数分数和o){
    d_分子=d_分子*o.d_分母+o.d_分子*d_分母;
    d_分母*=o.d_分母;
    归还*这个;
    }
    //显式转换为双精度
    显式运算符double()常量{
    返回静态(d_分子)/d_分母;
    }
    私人:
    int d_分子;
    int d_分母;
    };
    //添加两个分数的自由函数-按值取左侧
    //您可以返回相同的对象(在向其添加右侧之后)。
    分数运算符+(分数a、常数分数和b){
    //使用成员运算符+=
    返回a+=b;
    }
    

    在演示中,我使用了C++17函数,因为在处理分数时,数字越小越好,并且它具有支持打印的流媒体功能。