user2840470
user2840470

Reputation: 969

What is the difference in these two types of operator overloads?

I have been looking at some open source code and I see two different definitions of overloading an operator. What is the difference between them and are there any benefits of doing either?

For example, one example we have a class:

class foo{
public:
    void SetValue(double input_value) {foo_value = input_value};
    double GetValue() {return foo_value;}
private:
    double foo_value;
};

Then I sometimes see two different types / styles of overloading the addition operator (for example)

class foo{
    const foo operator+(const foo& input_foo);
};

const foo foo::operator+(const foo& input_foo) {
    foo_value += input_foo.foo_value;
    return *this;
}

The other type of overload I sometimes see is:

class foo{
    friend const foo operator+(const foo& input_foo1, const foo& input_foo2);
};

const foo operator+(const foo& input_foo1, const foo& input_foo2); // Defined right after class

const foo operator+(const foo& input_foo1, const foo& input_foo2) {
    foo temp_foo;
    temp_foo.SetValue(input_foo1.GetValue() + input_foo2.GetValue());
    return temp_foo;
}

Upvotes: 0

Views: 121

Answers (2)

Emilio Garavaglia
Emilio Garavaglia

Reputation: 20730

By an external point of view, foo::operator+(const foo&) and ::operaor+(const foo&, const foo&) plays exactly the same role in making meaningful the + symbol when placed between two foo-s. In particular the first is like the second when its own fisrt argument is *this.

By an internal point of view, they can have different capabilities in respect to the foo class: ::operaor+(const foo&, const foo&) is a "free function" (a function declared at global level): it has the beauty of the symmetry in treating the arguments in the same way, but cannot access foo's private data member, unless foo itself doesn't recognize it as its own firend.

foo::operator+(const foo&), as a member function, can have free access to all foo members and data but -as a member of foo- is less suitable to "generic algorithms" (that may prefer a functional form).

There are also some other difference about possible variants: consider

foo a;
foo b;
int k;

Both the operator+ seen above can give meaning to a+b, but what about a+k and k+a?

For a+k you can have either foo::operator+(int) or ::operator+(const foo&, int), but for k+a, you need ::operator+(int, const foo&) since there is no way to have + as a meber of int.

All that said, you declaration and implementation look "fuzzy" (or at least incoherent):

const foo foo::operator+(const foo& input_foo) {
    foo_value += input_foo.foo_value;
    return *this;
}

When you write c = a+b do you expect the value of a to change?

What you do, here, is adding b to a and create a copy of a (why const? it's a copy after all, and you already changed a) you assign then to c.

Operator + should create a new object whose value is the sum

foo foo::operator+(const foo& rop) const // NOTE THE SIGNATURE, make it coherent with the decalration { foo tmp; tmp.foo_value = foo_value + rop.foo_value; return tmp; }

It's not the return type, but the member-function itself to be const, as the parameter if given by reference, so that you ensure that in a+b neither a or b is changed. The return type is just a plain value you can let your caller to treat as it wants, since it is returned into his own stack-frame.

Upvotes: 0

ravi
ravi

Reputation: 10733

One overload is member function whereas other is free function.

You use free function so as to provide mixed-mode arithmetic. For e.g:-

foo f;
2 + f;    __1

__1 would compile only if there is free function operator+. Member function operator+ won't do anything in this case.

Upvotes: 3

Related Questions