代码之家  ›  专栏  ›  技术社区  ›  tunnuz

运算符>=重载的奇数行为

  •  2
  • tunnuz  · 技术社区  · 17 年前

    我在C++中有一个奇怪的行为,操作符重载。我有一个类,我需要检查它的内容是否大于或等于长双精度。我超载了>=操作员要进行此项检查,我的声明如下:

    bool MyClass::operator>=(long double value) const;
    

    我必须说,我的类也有一个cast-to-long-double操作符,它只在某些条件下工作,没有例外。 现在,当我使用这个操作符时,编译器抱怨操作符>=可供选择的方案是:

    • 矿
    • 内置的 operator>=(long double, int) .

    6 回复  |  直到 11 年前
        1
  •  3
  •   Johannes Schaub - litb    11 年前

    2015年更新: 或者,如果您想使用 (double)obj 语法,而不是 obj.to_double() explicit 在它前面加上那个关键字。然后需要显式强制转换才能转换为触发器。就我个人而言,我更喜欢 .to_double 语法,除非转换为 bool 因为在这种情况下,转换由 if(obj) 即使是 if(obj.to_bool()) 在我看来。


    删除转换运算符。它会一路带来麻烦。具有如下功能

    to_double()
    

    对于手头的问题,存在以下问题:

    obj >= 10
    

    考虑这个表达式。内置运算符使用转换运算符long double()通过用户定义的类型转换序列匹配第一个参数。但是,您的函数通过从int到long double(整数到浮点转换)的标准转换序列匹配第二个参数。当有两个参数的转换时,它总是模棱两可的,但至少没有一个参数可以更好地转换,而其余的参数在一次调用中转换得更差。在您的例子中,内置参数更好地匹配第二个参数,但第一个参数更差,但是您的函数更好地匹配第一个参数,但第二个参数更差。

    这很让人困惑,所以这里有一些例子(从char到int的转换称为升级,这比从char到int以外的东西的转换更好,后者称为转换):

    void f(int, int);
    void f(long, long);
    f('a', 'a');
    

    调用第一个版本。因为第一个的所有参数都可以更好地转换。同样,以下内容仍将称为第一个:

    void f(int, long);
    void f(long, long);
    f('a', 'a');
    

    因为第一个可以转换得更好,而第二个不会转换得更差。但以下是 模棱两可的 :

    void f(char, long);
    void f(int, char);
    f('a', 'a'); // ambiguous
    

    在这种情况下更有趣。第一个版本以完全匹配的方式接受第一个参数。第二个版本以完全匹配的方式接受第二个参数。但这两个版本至少不能同样好地接受他们的另一个论点。第一个版本要求对其第二个参数进行转换,而第二个版本要求对其参数进行升级。因此,即使升级比转换更好,对第二个版本的调用也会失败。

    这和你上面的情况很相似。即使标准转换序列(从int/float/double转换为long double)是 较好的 与用户定义的转换序列(从MyClass转换为long double)相比,不会选择运算符版本,因为您的其他参数(long double)需要从参数进行转换,这比内置运算符对该参数的转换更差(完全匹配)。

    过载解决是C++中的一个复杂问题,所以人们不可能记住它中的所有细微规则。但是得到粗略的计划是很有可能的。我希望它能帮助你。

        2
  •  3
  •   CB Bailey    17 年前

    通过向 double 你的意思是,我的班级相当于 双重的 因此,如果内置操作符>=对于 双重的 使用s。如果你 做 双重的 你应该考虑不提供 含蓄的 转换为 ,而是提供 明确的

    t >= d 哪里 t 是您的类的实例,并且 d T 的 operator double 调用,并且内置运算符>=对于 使用s,或d必须升级为a long double

    编辑,您已经更新了您的问题,建议将您的转换为长双精度,并将您的比较与整数进行比较。在这种情况下,最后一段应为:

    你现在有歧义的原因是因为一个表达式 t>=D 是您的类的实例,并且 D 是一个 int 的 operator long double 长双人 和 int 长双人

        3
  •  1
  •   dalle    17 年前

    我想你是在和文字作比较 int long double :

    MyClass o;
    
    if (o >= 42)
    {
       // ...
    }
    

    如果是这种情况,两种备选方案都一样好/复杂。

    用你的 operator long double() :

    1. MyClass::operator long double()
    2. operator>=(long double, int)

    MyClass::operator>=(long double) :

    1. 内置转换 int
        4
  •  0
  •   Daniel Earwicker    17 年前

    你有 long double double .

        5
  •  0
  •   Assaf Lavie    17 年前

    它是将自己转换成一个双精度的,还是可以与双精度进行比较?使用.greaterThan(double)函数不会达到同样的目的,但不会让用户感到惊讶吗?

    (灵感来源于FQA的精彩 rant about operator overloading )

        6
  •  0
  •   Mr.Ree    17 年前

    看起来您已经定义了:

    bool class::operator>=(long double value) { return value >= classValue; }
    

    而你却错过了:

    bool class::operator>=(double value)      { return value >= classValue; }
    bool class::operator>=(int value)         { return value >= classValue; }
    

    也许模板化的函数(或方法)会有所帮助?

    注意以下情况: a>=B 调用不同于 b>=A.