[英]Overloading * multiplication operator twice as a member function?
Scroll down for TL:DR. 向下滚动以获取TL:DR。
This question is similar to this one, but has some differences. 这个问题与此类似,但是有一些区别。 It concerns overloading the
*
operator twice for a class called jVector
, which simply represents a two-dimensional cartesian vector. 它涉及到对名为
jVector
的类的两次重载*
运算符,该类仅表示二维笛卡尔向量。
The first type of multiplication is jVector * jVector
, or a dot product . 第一种乘法是
jVector * jVector
或点积 。 The second type is multiplication by a real number, double * jVector
. 第二种类型是乘以实数
double * jVector
。 This simply returns a vector with its entries multiplied by the double. 这只是返回一个向量,其条目乘以double。
Here is some code to illustrate what I'm trying to do: 这是一些代码来说明我正在尝试做的事情:
class jVector{
public:
double x, y;
jVector(double x_val = 0., double y_val = 0.){
x = x_val;
y = y_val;
}
//Operator overload functions
//[...]
//F1: Dot product (WORKS)
double operator* (jVector& factor){
double result;
result = x * factor.x;
result += y * factor.y;
return result;
}
//F2: Real number multiplication (DOES NOT WORK)
jVector operator* (double f){
jVector result;
result.x = x * f;
result.y = y * f;
return result;
}
//[...]
}
//F3: As a non-member (WORKS)
jVector operator* (double f, jVector V){
jVector result;
result.x = V.x * f;
result.y = V.y * f;
return result;
}
The three relevant functions are marked F1
, F2
and F3
. 三个相关功能标记为
F1
, F2
和F3
。 The functions F2
and F3
are never defined at the same time (I comment out one of them to test the other). 函数
F2
和F3
永远不会同时定义(我注释掉其中一个来测试另一个)。
Here is the result of trying to express something like 2.0 * Foo
, where Foo
is a vector of type jVector
. 这是尝试表示类似
2.0 * Foo
,其中Foo
是jVector
类型的jVector
。 The operation works as expected when using F3
, the function which is defined outside the class. 使用类外部定义的函数
F3
,该操作将按预期工作。 However, when using only F2
, the member function, an error is raised which says no match for 'operator*' in '2 * Foo'
. 但是,仅使用成员函数
F2
,将引发错误,提示no match for 'operator*' in '2 * Foo'
。
This is the same type of error which you get if you don't overload an operator at all, suggesting that I didn't define F2
properly, or F2
is conflicting with F1
. 如果根本不重载运算符,则这与错误类型相同,这表明我没有正确定义
F2
或F2
与F1
冲突。
I'm fairly certain my problem is different from the one in the question I mentioned earlier, since F1
and F2
have different return types and argument types. 我可以肯定地说,我的问题与前面提到的问题有所不同,因为
F1
和F2
具有不同的返回类型和参数类型。
TL:DR TL:DR
So here's my question: why am I able to overload *
twice, only as long as one of them is defined as a non-member function? 所以这是我的问题:为什么仅当其中一个被定义为非成员函数时,我才能重载
*
两次? Why can't both overload functions be members of the class? 为什么两个重载函数都不能成为类的成员?
For member function operator overloads, the first operand must be an object of the class. 对于成员函数运算符重载,第一个操作数必须是该类的对象。 The parameter of the overloaded function is the second operand.
重载函数的参数是第二个操作数。 So:
所以:
double operator* (double f){
only applies to the case where you are doing a_vector * a_double
, and not to a_double * a_vector
. 仅适用于正在执行
a_vector * a_double
,不适用于a_double * a_vector
。
For this reason (and others) it's generally better to use non-member functions for overloaded operators. 由于这个原因(以及其他原因),通常最好对重载的运算符使用非成员函数。 The way I would suggest doing it is:
我建议这样做的方式是:
// member function
jVector & jVector::operator*=( double f )
{
x *= f;
y *= f;
return *this;
}
// free functions
jVector operator* (double f, jVector V) { return V *= f; }
jVector operator* (jVector V, double f) { return V *= f; }
It doesn't work as a member function because your F2 alternative takes a jVector
as the first operand ALWAYS (it is a member function, so you don't have a choice of what the first argument is - it is jVector *this
[hidden by the language]). 它不能用作成员函数,因为F2替代项始终将
jVector
用作第一个操作数(它是成员函数,因此您无法选择第一个参数是什么-它是jVector *this
[hidden根据语言])。 The compiler could in theory allow the two operands to swap place (it could for x * 2.0
convert to 2.0 * x
for regular math operations, but since operator overloads aren't made to be "swapped around", that wouldn't be very good if the compiler DID re-arrange them) 理论上,编译器可以允许两个操作数交换位置(对于常规的数学运算,它可以将
x * 2.0
转换为2.0 * x
,但是由于运算符重载不会被“交换”,所以不是很容易如果编译器DID重新排列它们很好)
For the first operand to be double
, you need a freestanding function. 为了使第一个操作数成为
double
,您需要一个独立的函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.