0

我正在尝试在 C++ 中实现一个类 COMPLEX 并重载算术运算符以及用于输入/输出的 '<<' 和 '>>' 运算符。单独和级联算术运算符按预期工作 - 但是在尝试执行以下语句时我无法获得正确的结果:

cout &lt&lt "something" &lt&lt complex1 + complex2 &lt&lt "\n";

其中 complex1 和 complex2 是 COMPLEX 类的对象。

类定义的片段:

class COMPLEX{
    int a;  // Real part
    int b;  // Imaginary part
public:
    COMPLEX operator = (COMPLEX );
    COMPLEX operator + (COMPLEX ) const;
    friend istream& operator &gt&gt (istream &, COMPLEX &);
    friend ostream& operator &lt&lt (ostream &, COMPLEX &);
-snip-
}


COMPLEX COMPLEX::operator = (COMPLEX t_c) {
    return COMPLEX(a = t_c.a, b = t_c.b);
}

COMPLEX COMPLEX::operator + (COMPLEX t_c) const{
    return COMPLEX(a + t_c.a, b + t_c.b);
}

istream& operator &gt&gt (istream &i_s, COMPLEX &t_c){
    i_s &gt&gt t_c.a &gt&gt t_c.b;
    return i_s;
}

ostream& operator &lt&lt (ostream &o_s, COMPLEX &t_c){
    o_s &lt&lt t_c.a &lt&lt "+" &lt&lt t_c.b &lt&lt "i";
    return o_s;
}

除此之外,我还重载了运算符。

当我尝试将 << 与任何其他重载运算符级联时,重载的 << 友元函数不会被调用。相反,操作员被调用并显示结果。

4

4 回答 4

1

问题是您的流插入运算符定义为

friend ostream& operator << (ostream &, COMPLEX &);

这将COMPLEX对象的非常量引用作为第二个参数。当你尝试写作时

cout << a + b << endl;

的值a + b右值,而不是左值,因为它是函数返回的值operator +。在 C++ 中,您不能将引用绑定到右值,从那时起您可能会做这样的坏事:

COMPLEX& c = a + b; // This step isn't legal
c = 137;            // Wait, what object did we just change?

这里的问题是,如果我们可以将引用绑定c到由 返回的临时对象a + b,那么我们可以使用该引用对该对象进行更改。但这没有任何意义 -a + b是表达式的值,而不是实际对象。

这与这里发生的问题相同。您的operator <<函数不能a + b作为第二个参数,因为a + b它是一个右值。

要解决此问题,您可以更改operator <<const引用 COMPLEX:

friend ostream& operator<< (ostream& out, const COMPLEX& c);

这是有效的,因为在 C++ 中,您可以将 const 引用绑定到右值。这背后的基本原理是,如果您有对临时对象的 const 引用,则无法对该临时对象进行任何更改,因此上述绑定引用的示例a + b不再是问题。

通常,任何接受其类型为不修改该实例的类的另一个实例的参数的重载运算符都应通过 const 引用获取其参数。这适用于, 等operator =operator +因为它避免了这个问题。

于 2011-02-05T20:54:16.220 回答
1

您的运算符 << 需要采用常量引用,否则,编译器将无法将 COMPLEX 类型的临时(由加法产生)转换为非常量引用,并且可能会寻找替代运算符 << 到称呼。

friend ostream& operator << (ostream &, const COMPLEX &); //notice "const"

要了解其余的运算符机制,您只需要查看运算符优先级表

于 2011-02-05T20:51:09.170 回答
0

您的问题是 operator<< 总是在 operator+ 之前调用。您提供重载的事实并没有改变这一点。

另一方面,您通常不应该将计算与 I/O 混合在一起(也许只是为了节省一些输入),因为这会使您很难看到计算的顺序。

于 2011-02-06T11:16:17.113 回答
0

cout将您的陈述重写为

cout << "something" << (complex1 + complex2) << "\n";
于 2011-02-05T20:25:52.527 回答