[英]Odd behavior with operator>= overloading
我在C ++中有一个运算符重载的奇怪行为。 我有一个课程,我需要检查其内容是否大于或等于一个长整数。 我重载了> =运算符以进行此检查,我的声明如下:
bool MyClass::operator>=(long double value) const;
我必须说,我的班级也有一个强制转换为双精度双精度运算符,该运算符仅在特定条件下才能正常工作。 现在,当我使用该运算符时,编译器会抱怨运算符> =的使用模棱两可,替代方法是:
operator>=(long double, int)
。 现在,如何强制程序使用我的运算符?
2015年更新:或者,如果您想使用(double)obj
语法而不是obj.to_double()
语法保持转换能力,请在该转换函数前添加该关键字作为前缀来使其explicit
。 您需要显式强制转换,然后才能触发转换。 就我个人而言,我更喜欢.to_double
语法,除非将转换转换为bool
因为在那种情况下,即使if if(obj)
是explicit
,转换也被if(obj)
使用,并且比if(obj.to_bool())
更具可读性。在我看来。
删除转换运算符。 它将一直引起麻烦。 具有像
to_double()
或类似的返回double值并显式调用该函数以获取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 ++中的一件事,因此不可能记住其中的所有微妙规则。 但是,制定粗略的计划是完全可能的。 我希望它对你有所帮助。
通过有效地说明对double
的隐式转换,您可以有效地说明这一点,我的类等效于double
,因此,您不必在意是否使用了double
的内置运算符> =。 如果您确实关心的话,那么您的类实际上就不等同于double
并且您应该考虑不提供对double
的隐式转换,而应提供显式的 GetAsDouble或ConvertToDouble成员函数。
您目前不清楚的原因是,对于表达式t >= d
,其中t
是类的实例,而d
是双精度型,编译器总是必须提供左侧或右侧的转换。如此一面手的表情确实是am昧的。 要么调用t
的operator double
,然后使用针对double
s的内置运算符> =,要么必须将d提升为long double
然后使用成员运算符> =。
编辑,您已经更新了问题,建议您将转换为long double,并将比较与int进行比较。 在这种情况下,最后一段应为:
您目前不清楚的原因是,对于表达式t >= d
,其中t
是类的实例,而d
是int
,编译器始终必须提供左侧或右侧的转换。如此一面手的表情确实是am昧的。 要么调用t
的operator long double
,然后使用内置运算符> =来表示long double
和int
,要么必须将d提升为long double
并使用成员运算符> =。
我假设您正在与文字int
进行比较,而不是long double
int
:
MyClass o;
if (o >= 42)
{
// ...
}
如果是这样的话,两种选择都一样好/复杂。
使用operator long double()
:
MyClass::operator long double()
operator>=(long double, int)
使用您的MyClass::operator>=(long double)
:
int
转换为long double
MyClass::operator>=(long double)
您的声明中有long double
。 尝试将其更改为double
。
看起来您已经定义了:
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不同的方法的情况 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.