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

时间:2015-02-11 23:51:42

标签: c++ overloading

向下滚动TL:DR。

此问题与this类似,但有一些差异。它涉及为名为*的类重载jVector运算符两次,它只是表示二维笛卡尔向量。

第一种乘法是jVector * jVectordot product。第二种类型乘以实数double * jVector。这只是返回一个向量,其条目乘以double。

以下是一些代码来说明我正在尝试做的事情:

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;
}

三个相关功能标记为F1F2F3。函数F2F3永远不会同时定义(我会注释掉其中一个来测试另一个)。

以下是尝试表达2.0 * Foo之类的结果,其中FoojVector类型的向量。使用F3时,该操作按预期工作,该函数在类外定义。但是,当仅使用成员函数F2时,会出现一个错误no match for 'operator*' in '2 * Foo'

如果您根本不重载运算符,则会出现相同类型的错误,表明我没有正确定义F2,或者F2与{{1}冲突}}

我非常确定我的问题与前面question I mentioned中的问题不同,因为F1F1具有不同的返回类型参数类型

TL:DR

所以这是我的问题:为什么我能够重载F2两次,只要其中一个被定义为非成员函数?为什么两个重载函数都不能成为类的成员?

2 个答案:

答案 0 :(得分:2)

对于成员函数运算符重载,第一个操作数必须是该类的对象。重载函数的参数是第二个操作数。所以:

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; }

答案 1 :(得分:2)

它没有作为成员函数工作,因为你的F2替代方案需要jVector作为第一个操作数总是(它是一个成员函数,所以你不能选择什么第一个参数是 - jVector *this [由语言隐藏])。理论上,编译器可以允许两个操作数交换位置(可以x * 2.0转换为2.0 * x进行常规数学运算,但由于操作符重载不能被交换围绕",如果编译器DID重新安排它们,这将不是很好)

对于第一个操作数为double,您需要一个独立的功能。