我有以下代码
class rectangle
{
//Some code ...
int operator+ (rectangle r1)
{
return(r1.length + length);//Length is the 1st argument of r1, r2, r3
}
};
在主要功能
int main()
{
rectangle r1(10,20);
rectangle r2(40,60);
rectangle r3(30,60);
int len = r1 + r3;
}
如果我们在operator+()
中看到,我们正在r1.length + length
。
编译器如何知道return语句中的第二个length
属于对象r3
而不属于r1
或r2
?
我想答案可能在我们写的main()
int len = r1 + r3;
如果是这种情况,那么为什么我们需要写入
operator+ (....)
{
r1.lenth + lenth; //Why not length + length?
}
为什么不length + length
?因为编译器已经从main()
知道first length
属于object
r1
而2nd
属于object
r3
。
答案 0 :(得分:5)
您将变量名称与参数名称混淆。在运算符重载中,您将参数命名为r1
:
int operator+(rectangle r1)
{
return(r1.length+length);
}
这意味着无论您传递给operator +
的任何参数,在运算符的主体内,它都将被命名为r1
(无论其原始名称如何)。
r1.length
是参数的长度,length
是当前对象的长度(即this->length
)。
//为什么不长度+长度?
这只会返回当前对象长度的两倍。
让我们分析代码:
rectangle r1(10,20);
rectangle r2(40,60);
rectangle r3(30,60);
int len = r1+r3;
最后一次通话相当于r1.operator+(r3)
。在运算符内,length
代表r1.length
,r1.length
代表r3.length
。实际上,甚至不是r3.length
,因为你正在通过值传递,并且将创建一个副本。通常的语法是:
int operator+(const rectangle& r1)
{
return(r1.length+length);
}
此外,添加矩形并没有多大意义,至少你是如何定义它的。添加两个矩形返回长度之和并不直观。它至少应该返回不同的形状。
答案 1 :(得分:2)
对象内的每个变量都与另一个对象的变量不同。 只有通过参数将对象传递给它时,编译器才会知道。它没有其他方法可以了解这一点。调用该函数时,将在堆栈上创建对象的副本。您在参数列表中指定的名称将是编译器将使用的名称,无论您在调用函数时使用的名称如何。
int operator+(rectangle r1)
{
return(r1.length+length);
}
r1 + r3; //In main
在此示例中,函数调用中对象的名称为r1
。你可以说出任何名称。编译器在main中调用时,不知道它的名称是r3
。
你从函数返回一个整数。最好创建一个临时对象并按值返回。
答案 2 :(得分:2)
int len = r1 + r3;
这解决了
int len = r1.operator+(r3);
因此,在r1对象上调用该方法,对operator+
中成员的任何引用都将是r1
的成员,而r3是该方法的实际参数。
答案 3 :(得分:1)
编译器需要将矩形的长度成员变量this->length
与r1.length
区分开来。编写length + length
意味着本地范围中的变量this->length
将用于添加的两侧。
答案 4 :(得分:1)
运算符类似于class rectangle
的成员函数,但具有另一种调用格式。
您也可以按照其他用户的建议调用函数int len = r1.operator+(r3);
。
因此,当您使用类中的运算符编写操作时,编译器会尝试将调用与某些给定的运算符进行匹配;在你的电话中:
int len = r1+r3;
编译器会查找operator+
,该int
会返回可以放入rectangle
的内容并接收int operator+(rectangle r1)
作为参数,并找到您的r3
函数;然后使用int
参数调用此函数并返回int operator+(rectangle r1)
结果。
r3
函数的参数是r3
的副本,因此,这就是r1
而不是r2
的原因}或operator+
。
这个问题没有提及,但我认为值得一提:
您的rectangle
似乎不适合运营商通常遵循的模型,如果您要添加rectangle
并从操作中获取与rectangle
不同的对象它看起来不像运营商;我认为你必须考虑你想要得到什么以及class rectangle
{
// Reference in order to avoid copy and const because we aren't going to modify it.
// Returns a rectangle, so it can be used on operations chain.
rectangle operator+(const rectangle &r) const
{
rectangle Result;
// Do wathever you think that must be the addition of two rectangles and...
return Result;
}
};
int main()
{
rectangle r1(10,20);
rectangle r2(40,60);
rectangle r3 = r1 + r2;
// Operation chain
rectangle r4 = r1 + r2 + r3;
rectangle r5 = r1 + r2 + r3 + r4;
// Is this what you're looking for?
int width = (r1 + r3).width();
int height = (r1 + r3).height();
}
的概要是什么。
作为binary operator,它通常会获取并返回相同类型的对象(为了在操作链中使用它),并且必须是const,因为它不会更改对象本身:
class rectangle
{
// Reference in order to avoid copy and const because we aren't going to modify it.
// Returns a rectangle, so it can be used on operations chain.
rectangle &operator+=(const rectangle &r) const
{
// Do wathever you think that must be the addition of two rectangles and...
return *this;
}
};
int main()
{
rectangle r1(10,20);
rectangle r2(40,60);
rectangle r3 = r1 + r2;
// Weird operation chain, but it's only an example.
rectangle r4 = (r1 += r2) += r3;
rectangle r5 = (r1 += r2) += (r3 += r4);
}
如果它是unary operator,则参数和返回值也必须是同一类型,但返回值必须是参与操作的对象:
{{1}}
答案 5 :(得分:0)
运算符重载不会比常规函数调用更多/不少。
将a+b
视为a.operator+(b)
。
除了奇怪名称之外,该呼叫与a.add(b)
中没有区别。
如果函数add
签名是int A::add(A x)
(其中A是一个类),则b被复制到x中,并且-inside add body-x和a的所有成员都可以访问。
但这与运营商没有什么特别之处。它涉及参数传递(C ++默认为“by copy”)变量范围和可见性。
如果你能理解,运算符重载应该是显而易见的。如果不能,请退回到“功能,成员函数和参数”,并且不要离开那里,直到这些概念不明确。