重载 * 乘法运算符两次作为成员函数?
Overloading * multiplication operator twice as a member function?
向下滚动 TL:DR。
此题与this题相似,但有一些不同。它涉及为名为 jVector
的 class 重载 *
运算符两次,它仅表示二维笛卡尔向量。
第一种乘法是jVector * jVector
,或dot product。第二种是乘以实数,double * jVector
。这只是 return 一个向量,其条目乘以双精度。
下面是一些代码来说明我正在尝试做的事情:
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;
}
三个相关函数被标记为F1
、F2
和F3
。函数 F2
和 F3
永远不会同时定义(我注释掉其中一个以测试另一个)。
这是尝试表达类似 2.0 * Foo
的结果,其中 Foo
是类型 jVector
的向量。当使用 F3
时,该操作按预期工作,该函数定义在 class 之外。但是,当仅使用成员函数 F2
时,会出现错误 no match for 'operator*' in '2 * Foo'
.
如果您根本不重载运算符,这与您遇到的错误类型相同,表明我没有正确定义 F2
,或者 F2
与 F1
.
我相当确定我的问题与之前 question I mentioned 中的问题不同,因为 F1
和 F2
具有不同的 return 类型 和参数类型。
TL:DR
所以这是我的问题:为什么我能够重载 *
两次,只要其中一个被定义为非成员函数?为什么两个重载函数不能都是 class 的成员?
对于成员函数运算符重载,第一个操作数 必须是class 的对象。重载函数的参数是第二个操作数。所以:
double operator* (double f){
仅适用于您正在执行 a_vector * a_double
的情况,不适用于 a_double * a_vector
。
出于这个原因(和其他原因),对重载运算符使用非成员函数通常更好。我建议这样做的方式是:
// 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; }
它不能用作成员函数,因为您的 F2 替代方案始终将 jVector
作为第一个操作数(它是一个成员函数,因此您无法选择第一个参数是什么是 - 它是 jVector *this
[被语言隐藏])。理论上,编译器可以允许两个操作数交换位置(它可以将 x * 2.0
转换为 2.0 * x
以进行常规数学运算,但由于运算符重载不是 "swapped around",因此如果编译器 DID 重新安排它们就不会很好)
要使第一个操作数成为 double
,您需要一个独立函数。
向下滚动 TL:DR。
此题与this题相似,但有一些不同。它涉及为名为 jVector
的 class 重载 *
运算符两次,它仅表示二维笛卡尔向量。
第一种乘法是jVector * jVector
,或dot product。第二种是乘以实数,double * jVector
。这只是 return 一个向量,其条目乘以双精度。
下面是一些代码来说明我正在尝试做的事情:
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;
}
三个相关函数被标记为F1
、F2
和F3
。函数 F2
和 F3
永远不会同时定义(我注释掉其中一个以测试另一个)。
这是尝试表达类似 2.0 * Foo
的结果,其中 Foo
是类型 jVector
的向量。当使用 F3
时,该操作按预期工作,该函数定义在 class 之外。但是,当仅使用成员函数 F2
时,会出现错误 no match for 'operator*' in '2 * Foo'
.
如果您根本不重载运算符,这与您遇到的错误类型相同,表明我没有正确定义 F2
,或者 F2
与 F1
.
我相当确定我的问题与之前 question I mentioned 中的问题不同,因为 F1
和 F2
具有不同的 return 类型 和参数类型。
TL:DR
所以这是我的问题:为什么我能够重载 *
两次,只要其中一个被定义为非成员函数?为什么两个重载函数不能都是 class 的成员?
对于成员函数运算符重载,第一个操作数 必须是class 的对象。重载函数的参数是第二个操作数。所以:
double operator* (double f){
仅适用于您正在执行 a_vector * a_double
的情况,不适用于 a_double * a_vector
。
出于这个原因(和其他原因),对重载运算符使用非成员函数通常更好。我建议这样做的方式是:
// 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; }
它不能用作成员函数,因为您的 F2 替代方案始终将 jVector
作为第一个操作数(它是一个成员函数,因此您无法选择第一个参数是什么是 - 它是 jVector *this
[被语言隐藏])。理论上,编译器可以允许两个操作数交换位置(它可以将 x * 2.0
转换为 2.0 * x
以进行常规数学运算,但由于运算符重载不是 "swapped around",因此如果编译器 DID 重新安排它们就不会很好)
要使第一个操作数成为 double
,您需要一个独立函数。