我正在尝试用C ++实现一个COMPLEX类并重载算术运算符以及'<<'和'>>'输入/输出的运算符。单独地,也可以在级联时算术运算符按预期工作 - 但在尝试执行语句时我无法获得正确的结果:
cout << "something" << complex1 + complex2 << "\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 >> (istream &, COMPLEX &);
friend ostream& operator << (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 >> (istream &i_s, COMPLEX &t_c){
i_s >> t_c.a >> t_c.b;
return i_s;
}
ostream& operator << (ostream &o_s, COMPLEX &t_c){
o_s << t_c.a << "+" << t_c.b << "i";
return o_s;
}
除此之外我还重载了运营商。
当我尝试级联&lt;&lt;与任何其他重载运算符,重载&lt;&lt;朋友的功能没有被调用。而是调用操作符并显示其结果。
答案 0 :(得分:1)
您的运营商&lt;&lt;需要采用常量引用,否则,编译器将无法将临时类型COMPLEX(由添加产生)转换为非const引用,并且可能会寻找替代运算符&lt;&lt;打电话。
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混合(可能只是为了节省一些输入),因为这使得很难看到计算的顺序。