Do I have to return a reference to the object when

2020-02-06 02:01发布

问题:

Can I use:

MyClass& MyClass::operator++ () {
    a++;  // private var of MyClass
    return (*this);
}

Or it can be:

MyClass MyClass::operator++ ();

What's the difference?


Thanks for answers. I have another issue.

Many people do something like that:

MyClass& MyClass::operator++();
MyClass MyClass::operator++(int);

Isn't it illogical? Please give some examples if you can.

I know that the first version is pre-increment and the second is post-increment, but i ask why the first one returns reference but the second one not? It is in the same code (class), and the same use of the code.

回答1:

No, you don't have to return the reference to your object when you overload the pre-increment operator. In fact you may return anything you'd like, MyClass, int, void, whatever.

This is a design issue -- you must ask yourself what is the most useful thing to the users of your class that you are able to return.

As a general rule, class operators are the most useful when they cause the least confusion, that is, when they operate the most like operators on basic types. In this case, the pre-increment operator on a basic type:

int  i = 7;
j = ++i;

increments the variable and then returns the new value. If this is the only use you want MyClass to have, then returning a copy of your class is sufficient.

But, the pre-increment operator on a basic type actually returns an lvalue. So, this is legal:

int i = 7;
int *p = &++i;

If you want to support an operation like this, you must return a reference.

Is there a specific reason that you don't want to return a reference? Is that not a well-formed concept for your particular class? If so, consider returning void. In that case, this expression: ++myObject is legal, while this myOtherObject = ++myObject is not.



回答2:

You can return whatever you want. void, reference to self, copy of self, something else. Whichever you prefer (or need).

If you plan using the ++ operator in chained expressions (like (++obj).something()) then return a reference. In you don't, then void is just fine.

Remember that in the end, operators are just like normal methods: you can do whatever you want with them, provided you respect their prototype.



回答3:

For question two:

Prefix returns a reference, as expected. Postfix returns a copy to be consistent with the behavior of the postfix operator(s).

Break it down simply to int:

int c = 0;

if(++c)
{
   // true, prefix increments prior to the test
}

c = 0;

if(c++)
{
   // false, c now == 1, but was incremented after the test
}

Implementing this behavior in a class requires a copy be returned because the postfix operator will have modified the state of the object.

If the program does not need true postfix operation, you are free of course to implement how you wish. While there are standard ways of writing these operators (that are understood by most C++ programmers), there's nothing actually stopping you from implementing this in different ways.

The argument provided about incorrect functionality surrounding (obj++)++ is not really important, as that code won't even compile for POD types (in Visual Studio 2010, at least), because for POD types, a copy is returned and that temporary copy cannot be used alone as an l-value.

However, for the prefix operator a reference is the preferred return as that allows the proper behavior for chaining the operation (++(++obj)).



回答4:

Its not compulsory, but we should try to make operator overloading intuitive and it should work as per the operator which is being overloaded.

If we do int i = 10; i++ = 0 Then second statement is not allowed it says it requires lvalue as i++ denotes older state of i not a storage ... while ++i = 0 perfectly works fine .. so just to keep it in sync with actual operators prefix version had to return refence so that its return value may be treated as lvalue in expressions.



回答5:

Yes, you should return by reference. No need for the parenthesis around *this.

EDIT: Replying to your comment... You don't have to return by reference. But in general we follow some guidelines which make our classes behave "as expected" when compared to the builtin semantics of such operators. You might wanna take a look at http://www.parashift.com/c++-faq-lite/operator-overloading.html.