简体   繁体   English

作为成员函数两次重载*乘法运算符?

[英]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 . 三个相关功能标记为F1F2F3 The functions F2 and F3 are never defined at the same time (I comment out one of them to test the other). 函数F2F3永远不会同时定义(我注释掉其中一个来测试另一个)。

Here is the result of trying to express something like 2.0 * Foo , where Foo is a vector of type jVector . 这是尝试表示类似2.0 * Foo ,其中FoojVector类型的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 . 如果根本不重载运算符,则这与错误类型相同,这表明我没有正确定义F2F2F1冲突。

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. 我可以肯定地说,我的问题与前面提到问题有所不同,因为F1F2具有不同的返回类型参数类型。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM