是否可以使用重载算术运算符级联重载提取运算符?

时间:2011-02-05 20:16:45

标签: c++ overloading operator-keyword insertion

我正在尝试用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 个答案:

答案 0 :(得分:1)

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

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

要了解其余的操作员机制,您只需要查看operator precedence table

答案 1 :(得分:1)

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

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

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

cout << a + b << endl;

a + b的值是 rvalue ,而不是左值,因为它是函数operator +返回的值。在C ++中,你不能绑定对rvalue的引用,因为那时你可以做这样的Bad Things:

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引用绑定到rvalues。这背后的基本原理是,如果你有一个临时的const引用,你不能对该临时对象进行任何更改,所以上面绑定对a + b的引用的示例不再是问题。

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

答案 2 :(得分:0)

将您的cout声明重写为

cout << "something" << (complex1 + complex2) << "\n";

答案 3 :(得分:0)

你的问题是运营商&lt;&lt;总是在operator +之前调用。您提供重载的事实不会改变这一点。

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