C++中运算符重载的参数个数

Lem*_*urr 18 c++ operator-overloading

我正在学习C++,我创建了两个简单的hello-world应用程序.在他们两个中我使用运算符重载,但这是问题所在.在第一个,我可以提供两个参数重载运算符,它没关系.

标题:

enum Element {a,b,c,d,e};
Element operator + (Element x, Element y);
//more overloads for -, *, / here
Run Code Online (Sandbox Code Playgroud)

资源:

Element operator + (Element x, Element y) {
    return ArrayOfElements[x][y];
}
Run Code Online (Sandbox Code Playgroud)

但在我的第二个应用程序(简单的复数计算器) - 这种方法不起作用.在谷歌搜索并找出原因之后,我最终得到了这段代码:

标题:

struct Complex {
        double Re;
        double Im;

        Complex (double R, double I) : Re(R), Im(I) { }

        Complex operator + (Complex &Number);
        //more overloads
    };
Run Code Online (Sandbox Code Playgroud)

资源:

Complex Complex::operator + (Complex &Number)
    {
        Complex tmp = Complex(0, 0);
        tmp.Re = Re + Number.Re;
        tmp.Im = Im + Number.Im;
        return tmp;
    }
Run Code Online (Sandbox Code Playgroud)

它现在正在工作,但我想知道,为什么在第一段代码中我被允许在operator重载中放入两个参数,但是第二个我被给了以下错误?

complex.cpp:5:51: error: 'Complex Complex::operator+(Complex, Complex)' must take either zero or one argument
Run Code Online (Sandbox Code Playgroud)

每当我使用课程时都是一样的.我一直在寻找许多文档,第二种方式似乎更正确.也许是因为不同的论证类型?

使用-Wall -pedantic参数编译的两个源g++都使用相同的库.

Jon*_*rdy 30

假设你有一个这样的类:

class Element {
public:
    Element(int value) : value(value) {}
    int getValue() const { return value; }
private:
    int value;
};
Run Code Online (Sandbox Code Playgroud)

有四种方法可以定义二元运算符,例如+.

  1. 作为一个只能访问public类成员的自由函数:

    // Left operand is 'a'; right is 'b'.
    Element operator+(const Element& a, const Element& b) {
        return Element(a.getValue() + b.getValue());
    }
    
    Run Code Online (Sandbox Code Playgroud)

    e1 + e2 == operator+(e1, e2)

  2. 作为成员函数,可以访问该类的所有成员:

    class Element {
    public:
        // Left operand is 'this'; right is 'other'.
        Element operator+(const Element& other) const {
            return Element(value + other.value);
        }
        // ...
    };
    
    Run Code Online (Sandbox Code Playgroud)

    e1 + e2 == e1.operator+(e2)

  3. 作为一个friend功能,可以访问该类的所有成员:

    class Element {
    public:
        // Left operand is 'a'; right is 'b'.
        friend Element operator+(const Element& a, const Element& b) {
            return a.value + b.value;
        }
        // ...
    };
    
    Run Code Online (Sandbox Code Playgroud)

    e1 + e2 == operator+(e1, e2)

  4. 作为friend在类体外定义的函数 - 与#3的行为相同:

    class Element {
    public:
        friend Element operator+(const Element&, const Element&);
        // ...
    };
    
    Element operator+(const Element& a, const Element& b) {
        return a.value + b.value;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    e1 + e2 == operator+(e1, e2)

  • 如果它是一个成员函数,你可以做`Element(2)+ 3`而不是`2 + Element(3)`. (3认同)

NPE*_*NPE 7

如果您更喜欢operator+将两个操作数都作为显式参数,则必须将其定义为自由(即非成员)函数:

class Complex {
    friend Complex operator+(const Complex& lhs, const Complex& rhs);
}

Complex operator+(const Complex& lhs, const Complex& rhs) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

必须使用这种形式如果左操作数是基本类型,或一类,你不控制(因此不能添加一个成员函数)的。

  • ...如果可能有任何隐式转换到`Complex`,你应该使用这种形式。 (4认同)

tao*_*ocp 6

由于 + 是一个二元运算符,如果在结构体/类中重载它,则只能再提供一个操作数,原因是第一个操作数隐式是调用对象。这就是为什么在第一种情况下,您有两个参数,因为它超出了类/结构的范围,而在第二种情况下,它作为成员函数被重载。