我正在编译MegaInt类的一些c ++代码,这是一个正十进制类,允许对大数字进行算术运算。
我想重载operator bool以允许这样的代码:
MegaInt m(45646578676547676);
if(m)
cout << "YaY!" << endl;
这就是我所做的:
头:
class MegaInt
{
public:
...
operator bool() const;
};
const MegaInt operator+(const MegaInt & left, const MegaInt & right);
const MegaInt operator*(const MegaInt & left, const MegaInt & right);
实现:
MegaInt::operator bool() const
{
return *this != 0;
}
const MegaInt operator+(const MegaInt & left, const MegaInt & right)
{
MegaInt ret = left;
ret += right;
return ret;
}
现在问题是,如果我这样做:
MegaInt(3424324234234342) + 5;
它给了我这个错误:
'operator +'在'operator +'中的模糊重载(const MegaInt&amp;,const MegaInt&amp;) 注意:候选者是:operator +(int,int)| 注意:const MegaInt运算符+(const MegaInt&amp;,const MegaInt&amp;)|
我不知道为什么。如何导致操作符+的重载bool()变得模糊不清?¸
谢谢。
嗯,不幸的是,每个人都给了我很好的答案,他们似乎都没有完全解决我的问题。
void *或Safe Bool Idiom都可以。除了一个小问题,我希望有一个解决方法:
与0比较时:
if (aMegaInt == 0)
编译器再次出现模糊的重载错误。我理解为什么:它不知道我们是在比较假,还是在比较值为0的MegaInt。尽管如此,在这种情况下,我希望它转换为MegaInt(0)。有没有办法强迫这个?
再次感谢你。
答案 0 :(得分:12)
允许C ++编译器自动将bool
转换为int
,这就是它想要做的事情。
解决此问题的方法是使用safe bool idiom。
从技术上讲,创建operator void*
不是安全bool习语的一个例子,但在实践中它足够安全,因为你遇到的bool / int问题很常见错误,并且弄乱了一些完全合理且正确的代码(正如您从问题中看到的那样),但是void*
转换的误用并不常见。
答案 1 :(得分:3)
explicit conversion operators for C++0x上的维基百科条目对您在C ++ 0x之前看到此错误的原因有一个很好的总结。基本上,bool
转换运算符是一个完整的转换类型,因此它将用于整数算术表达式。前C ++ 0x修复程序将使用void *
作为转换运算符; void *
可以转换为布尔表达式,但不能转换为整数表达式。
答案 2 :(得分:2)
正如Erik的回答所述,这里的问题是通过向bool
提供隐式转换,你打开了表达可能意味着多种事物的表达的大门;在这种情况下,编译器会抱怨含糊不清并给出错误。
但是,请注意,向void*
提供隐式转换不会让您摆脱困境;它只会改变出现问题的表达式集。
这个问题有两个不透明的解决方案:
bool
(如果类表示具有直观“true / false”值的实体,则可能不合适)答案 3 :(得分:1)
问题是bool
可以自由转换为int
。所以表达式MegaInt(3424324234234342) + 5;
可以同样有效地解释为:
(bool)(MegaInt(3424324234234342)) + 5;
或:
MegaInt(3424324234234342) + MegaInt(5);
这些表达式中的每一个都涉及一个用户定义的转换,并且在编译器的眼中是相同的。由于这个原因,转换为bool
非常有问题。如果有一种方式可以说它应该只发生在明确需要bool
的上下文中,那就太棒了,但事实并非如此。 : - /
转换为其他人建议的void *
是一种解决方法,但我认为作为一种解决方法,它有自己的问题,我不会这样做。
答案 4 :(得分:0)
MegaInt(3424324234234342) + 5;
MegaInt + int;
编译器应该将MegaInt转换为整数(bool是整数类型)还是整数转换为MegaInt(你有一个int构造函数)?
您可以通过创建operator void *
而不是operator bool
来解决此问题:
operator void *() const { return (*this != 0) ? ((void *) 1) : ((void *) 0); }
答案 5 :(得分:0)
其他人提到了Safe Bool Idiom。但是,对于像你这样的对象,当你想要完整的代数支持时,添加所有这些讨厌的特殊逻辑是一个坏主意。
您正在定义自定义整数类型。通过定义“operator ==”和“operator!=”,然后将“operator bool()”实现为:
,您可以获得更多的努力。operator bool()
{
return (*this != 0);
}
从这三个函数中你可以获得整数的所有“if”习语,并且它们对于你的自定义整数的行为与内置函数相同:“if(a == b)”,“if (a!= b)“,”if(a)“,”if(!a)“。你的隐含“bool”规则也会(如果你小心)直观地工作。
此外,完整的“安全布尔成语”是不必要的。想一想 - 你需要它的唯一时间是“1)2个对象的比较是错误定义的或未定义的,2)转换为(int)或其他原始类型需要保护3)对象有效性是明确定义的(返回布尔的实际来源)。“
嗯,2)只是一个考虑,如果你真的希望支持转换为数字类型,如int或float。但是对于那些没有明确定义的平等概念的对象(#1),提供这样的演员阵容不可避免地会产生非常“if(a == b)”逻辑炸弹的风险,这些成语可能会保护你。只需声明“operator int()”和私有就像你在不可复制对象上复制ctor那样私有并完成它:
class MyClass {
private:
MyClass(const MyClass&);
operator int();
operator long();
// float(), double(), etc. ...
public:
// ctor & dtor ..
bool operator==(const MyClass& other) const { //check for equality logic... }
bool operator!=(const MyClass& other) const { return !(*this == other); }
operator bool() { return (*this != 0); }
};