指向类的指针

Pointer to class

本文关键字:指针      更新时间:2023-10-16

我一直在尝试编写Fraction类并重载它的一些运算符(+,-,-,/…(。起初,我尝试这样做:

Fraction& operator+(Fraction& rightOp)
{
    Fraction result;
    result.num = num * rightOp.den + den * rightOp.num;
    result.den = den * rightOp.den;;
    return result;
}

这产生了一个尴尬的结果。测试时,如果我使用:

Fraction a(2,3);
Fraction b(4,5);
Fraction c = a + b;
cout << c << endl;

它将正确打印。但是,如果我使用:

Fraction a(2,3);
Fraction b(4,5);
Fraction c;
c = a + b;
cout << c << endl;

它将打印-858993460/-858993460。

然后,当我试图将重载函数更改为:

Fraction& operator+(Fraction& rightOp)
{
    Fraction* result = new Fraction;
    result->num = num * rightOp.den + den * rightOp.num;
    result->den = den * rightOp.den;
    return *result;
}

一切都会好起来的。这让我对指向C++中的类感到困惑,我真的不明白为什么第一个类在特定情况下失败。如有任何解释,我将不胜感激。

提前谢谢。

注:运算符<lt;不是问题的根源,但无论如何,问题就在这里:

friend ostream& operator<<(ostream& out, Fraction& f)
{
    out << f.num << "/" << f.den << endl;
    return out;
}
Fraction& operator+(Fraction& rightOp)
{
    Fraction result;
    result.num = num * rightOp.den + den * rightOp.num;
    result.den = den * rightOp.den;;
    return result;
}

问题是它返回了对局部变量的引用。局部变量在函数结束时被销毁,因此引用引用了一个无效对象。

使用new为您解决了问题,因为它使result对象动态分配。这样的对象在函数结束时是而不是销毁的。然而,这肯定不是解决问题的办法。operator+的用户完全不清楚返回的引用是指动态分配的对象,将来需要是deleted。永远不要给用户带来负担。

相反,您应该更改函数,使其按值返回:

Fraction operator+(Fraction& rightOp)
{
  // ...
  return result;
}

现在,这将返回result副本,因此result是否在函数结束时被销毁并不重要。

另外需要注意的是,您可能希望函数采用const Fraction&参数。这允许在第二个操作数是右值(通常是临时对象(时调用它。

您的+重载通过引用返回Fraction的实例。问题是Fraction的本地实例将在表达式a + b的末尾超出作用域,但c仍将保留对内存中该空位的引用。

引用返回不是您想要的。在这种情况下,更适合通过返回-:来进行复制

Fraction operator +(Fraction& rightOp)
{
    Fraction result;
    result.num = num * rightOp.den + den * rightOp.num;
    result.den = den * rightOp.den;;
    return result;
}

此外,建议您的>>重载通过const引用获取Fraction实例,因为它不会在主体内部修改它:

friend ostream& operator<<(ostream& out, Fraction const& f)
//                                                ^^^^^