我试着查阅了这本书,我在那里找到的原因是操作符函数的原型重载<<<; 操作员是:
friend ostream& operator<<(ostream&, const className&);
现在考虑以下语句:
cout << myRectangle << yourRectangle;
这个说法相当于这个说法:
operator<<(operator<<(cout, myRectangle), yourRectangle); //Line A
因为运算符<<; 是从左到右。 要执行前面的语句,必须先执行表达式:
cout << myRectangle
即表达式:
operator<<(cout, myRectangle)
执行此表达式(输出myRectangle的值)后,函数运算符<<<; 将成为运算符<<; (即函数运算符的第一个参数<<<) 为了输出对象yourRectangle的值(参见A行的语句)。 运算符<<; 必须是ostream类型的对象,因此表达式:cout<<<; myRectangle必须将对象cout(而不是它的值)返回到第二个运算符<<; 以便输出YourRectangle的值。 因此,函数运算符的返回类型<<<; 必须是对ostream类型对象的引用。
这意味着,在形参通过引用获取对象的情况下,不能将对象作为实参按值传递。 因此,在重载<<<; 接线员。 但让我感到困惑的是这句话:
tempRectangle = myRectangle + yourRectangle + anyRectangle;
根据运算符的优先级和关联性,编译器将首先执行:
myRectangle + yourRectangle
相当于:
myRectangle.operator+ (yourRectangle); // Line B
我的第一个困惑是,在执行B行之后,它将按值返回对象(然后将由第三个对象(即anyRectangle)添加)。 那么,如何按照B行来写这个加法(因为我们没有由值返回的对象的任何名称,所以它是如何执行这个加法的)。
第二个困惑是,在这个语句中添加了所有三个对象之后:
tempRectangle = myRectangle + yourRectangle + anyRectangle;
我们有一个return-by-value对象,然后将该对象传递给operator=function,以便为其分配TemPrecTangle。 现在,这是相同的情况,它发生了<<<; 接线员。 由于operator=函数的原型是:
className operator+(const className&) const;
这个函数还有一个引用参数。 但是我们将对象按值传递为一个实际的参数(在重载<<>运算符中,我们使用了按引用返回,因为我们必须将它传递给不能按值返回对象的引用参数,所以为什么我们在这里不这样做,即按引用返回)。
正如注释中提到的,operator=
应该返回一个引用。 另一方面,运算符+
是不同的,因为在
auto c = a + b;
运算符+
通常保持两个操作数不变,结果创建一个新对象。 例如
struct foo {
int value;
foo operator+(const foo& other) const {
foo result;
result.value = value + other.value;
return result;
}
};
如果将operator+
链接为
auto c = (a + b) + c;
则运算符+(c)
既不对a
也不对b
调用,而是对a+b
的结果调用。