请注意,这个问题与学校的作业有关。
我们正在构建一个自定义Fraction类,大多数运算符都被重载。他们中的大多数都没有给我带来麻烦。但是,这部分驱动程序对我不起作用:
cout << "testing post++ with f2 = f1++;" << '\n';
f2 = f1++;
cout << "f1 : " << f1 << '\n';
cout << "f2 : " << f2 << '\n';
assert(f1 == Fraction(6));
assert(f2 == Fraction(5));
cout << "ok\n\n";
f2被赋予了f1 ++的值,而不是预先递增的f1,这是断言假设的那个。
我的操作符如下:
Fraction Fraction::operator++(int a)
{
numer = (numer + denom);
normalize();
return *this;
}
现在,我正在摸不着头脑,因为在我的脑海中,逻辑是++优先于赋值运算符,所以我希望断言用post ++测试f1和f2的值相同操作。对于++ pre重载,断言值在驱动程序中彼此相等。
我的问题是,为什么f2应该采用f1的预递增值,以及如何修改我的运算符来实现这一点,或者这可能是教授的错误?
作业运营商:
Fraction& Fraction::operator=(const Fraction &rhs) {
numer = rhs.getNumer();
denom = rhs.getDenom();
return *this;
}
答案 0 :(得分:2)
后增量在增量之前返回值。这就是为什么当您在后缀return *this
或++
运算符中看到--
时,您应该立即知道实现是错误的。
正确的行动顺序如下:
*this
假设您的Fraction
类具有正常运行的复制构造函数,则修复非常简单:
Fraction Fraction::operator++(int a)
{
Fraction res(*this);
// The following two lines are most likely shared with the prefix ++
// A common trick is to call ++*this here, to avoid code duplication.
numer = (numer + denom);
normalize();
return res;
}
答案 1 :(得分:2)
当您在示例中遇到重载运算符问题时,查看语法糖并查看“真正”调用的内容通常会有所帮助。
f2 = f1++;
这个实际上翻译为:
f2.operator=(f1.operator++(0));
如果你暂时假设这些只是通常命名的函数,那就更清楚了:
f2.Assign(f1.PostIncrement());
现在应该很清楚会发生什么。首先调用PostIncrement
函数,并将其结果作为参数传递给Assign
。
重载运算符没有什么神奇之处。它们只是具有特殊名称的函数。返回值或传递参数没有特殊规则。因此,
Fraction Fraction::operator++(int a)
{
numer = (numer + denom);
normalize();
return *this;
}
,想像这样:
Fraction Fraction::PostIncrement()
{
numer = (numer + denom);
normalize();
return *this;
}
完全按照你所写的内容进行:它会自行递增,然后自行返回。
如果您想要与内置类型相同的后增量语义,则必须手动实现这些语义。在operator++(int)
中,首先创建*this
的临时副本,然后增加,然后返回临时副本。