slow
slow

Reputation: 825

overloaded operator<< and operator+ causing error

class student
{
 private:
     int age;
 public:
     student();
     student(int a) {age = a;}
     ~student() {};
     friend student& operator+ (int left, student& s);
     friend ostream& operator<< (ostream& o, student& s);
}

...

student& operator + (int left, student& s)
{
    s.age += left;
    return s;
}

ostream& operator<< (ostream& o, student& s)
{
    o << s.age << endl;
}


int main (void)
{ 
    student a (10);
    cout << 14 + a ;
    return 0;
}

So I have two questions from the above code.

  1. Why do you have to do return s; in the operator+ (int left, student& s) function? why can't you just put the return type as void since you're already passing student object by reference?

  2. It seems that I get an error whenever I put endl after 14 + a, I catch an error and it doesn't print. I know this has something to do with `operator <<', but I don't know the exact reason for it, and how do you prevent this from happening?

Upvotes: 2

Views: 111

Answers (3)

James Kanze
James Kanze

Reputation: 153899

Concerning 1, you don't have to do anything. The language imposes no restrictions on what you do with an overloaded operator. Maintainability and readability, on the other hand, do require that the overloaded operator behave in some way like the corresponding built-in operator. Thus:

  • It makes no sense to overload addition for a type named student, since it makes no sense adding students. (On the other hand, your class student really seems more like an abstraction of StudentAge.)

  • Addition (operator +) does not modify either of its arguments. With almost no exceptions. In your case (supposing StudentAge, rather than just Student), I could see three operators: StudentAge operator+( StudentAge const& lhs, int rhs ), StudentAge operator+( int lhs, StudentAge const& rhs ), and above all, StudentAge& StudentAge::operator+=( int rhs ). The last would change this, and the first two should probably be implemented in terms of this third overload.

  • All of the overloaded addition operators should return something, because this is what the built-in operator does. operator+ returns a new object, and operator+= returns a reference to this (return *this;). Again, always.

Anything else is abuse, and only serves to confuse the reader.

With regards to your second question: you've declared operator<< to return something, so implement it to return something. Just falling off the end is undefined behavior (even without anything else following).

Upvotes: 1

Andy Prowl
Andy Prowl

Reputation: 126412

Why do you have to do return s; in the operator+ (int left, student& s) function?

I must say your definition of operator + is strange, as it modifies the right side object - while operator + normally does not, and returns a new object by value.

Anyway, operator + normally does not return void so that it allows chaining, as in:

14 + (16 + a)

But again, operator + is not supposed to modify the right side object. You probably meant to write something like operator +=. Consider changing the definition of your operator +.

It seems that I get an error whenever I put endl after 14 + a, I catch an error and it doesn't print. I know this has something to do with `operator <<', but I don't know the exact reason for it, and how do you prevent this from happening?

Your program has undefined behavior, because your overload of operator << does not return anything. You should add a return statement:

ostream& operator<< (ostream& o, student const& s)
//                                       ^^^^^
{
    o << s.age << endl;
    return o;
//  ^^^^^^^^^ <== Without this, your program has undefined behavior.
//                Value-returning functions MUST return a value (with
//                the only exception of main())
}

Also, as done above, you should accept the student object by reference to const, since the operator << is not going to alter its state (if you didn't do that, you could not use operator << with a const object.

Upvotes: 6

Mike B
Mike B

Reputation: 478

For 1), consider the following code :

student aStudent = anotherStudent + aDifferentStudent;

Here, we take two arguments and return a value. This is why you need to return an instance of the class. Your current implementation is not a standard way of doing the operator+ function, as it modifies the arguments. Consider the string operator+ used here:

std::string aString = "Hello" + " " + "World";

Operating from right-to-left, " " and "World" are literal strings, passed to the function, which returns " World", which is then passed along with "Hello" to the function again (as you have 2 calls to the operator+ method) to finally return "Hello World". Your implementation cannot do that, as A) the function parameters are not declared const, and B) if they were, and it did a const-cast to modify, you'd be attempting to modify a string literal - undefined behaviour.

String is a good example of how one expects the operator+ overload to work, in order to avoid breaking the principal of least surprise.

As for your << and endl issue, this is similar in principal. You need to return the o instance.

Upvotes: 0

Related Questions