0

I am going through operator overloading in C++ and have a question.

What if both friend and member operator overloaded functions are present? Which will be called?

A minimal example for the + operator is below.

#include <iostream> class myTime { private: int mm,hh; public: myTime(): mm(0), hh(0) {} myTime(int mm1, int hh1) :mm(mm1), hh(hh1) {} myTime( const myTime & ref) : mm(ref.mm), hh(ref.hh) {} friend myTime operator +(myTime &t1, myTime &t2); myTime operator+ (const myTime &ref); void display() { std:: cout << " Hrs = " << hh << " mins = " << mm << std::endl;} }; myTime operator + (myTime &t1, myTime &t2) { int mm2, hh2; std::cout << "Friend Operator" << std::endl; mm2 = (t1.mm + t2.mm) %60; hh2 = (t1.mm + t2.mm)/60 + (t1.hh + t2.hh); return (myTime(mm2,hh2)); } myTime myTime::operator+ (const myTime &ref) { int mm2, hh2; std::cout << " Member operator" << std::endl; mm2 = (ref.mm + mm)%60; hh2 = (ref.mm + mm)/60 + (ref.hh + hh); return (myTime(mm2,hh2)); } int main() { myTime t1(30,3); myTime t2(50,4); myTime t3; t3 = t1+t2; t3.display(); } 

When run on my machine (gcc 4.8.3 Windows), the friend function is called. Will this be the same on all machines?

Edit With the + operator changed to const the member operator is executed.

public: myTime(): mm(0), hh(0) {} myTime(int mm1, int hh1) :mm(mm1), hh(hh1) {} myTime( const myTime & ref) : mm(ref.mm), hh(ref.hh) {} friend myTime operator +(const myTime &t1, const myTime &t2); myTime operator+ (const myTime &ref); void display() { std:: cout << " Hrs = " << hh << " mins = " << mm << std::endl;} }; 

again why?

2
  • When i add the const, the member operator is executed, again the question is why? Commented Aug 2, 2019 at 7:41
  • friend isn't really the issue here; that's an implementation detail. The question is about a non-member function versus a member function. Commented Aug 2, 2019 at 13:34

2 Answers 2

3

No, it will give you an error that the call is ambiguous. It was only able to resolve it in your example because one function uses const while the other doesn't, which is part of the signature. Try this instead:

#include <iostream> class myTime { private: int mm,hh; public: myTime(): mm(0), hh(0) {} myTime(int mm1, int hh1) :mm(mm1), hh(hh1) {} myTime( const myTime & ref) : mm(ref.mm), hh(ref.hh) {} friend myTime operator +(myTime const&t1, myTime const&t2); myTime operator+ (const myTime &ref) const; void display() { std:: cout << " Hrs = " << hh << " mins = " << mm << std::endl;} }; myTime operator + (myTime const& t1, myTime const& t2) { int mm2, hh2; std::cout << "Friend Operator" << std::endl; mm2 = (t1.mm + t2.mm) %60; hh2 = (t1.mm + t2.mm)/60 + (t1.hh + t2.hh); return (myTime(mm2,hh2)); } myTime myTime::operator+ (const myTime &ref) const { int mm2, hh2; std::cout << " Member operator" << std::endl; mm2 = (ref.mm + mm)%60; hh2 = (ref.mm + mm)/60 + (ref.hh + hh); return (myTime(mm2,hh2)); } int main() { myTime t1(30,3); myTime t2(50,4); myTime t3; t3 = t1+t2; t3.display(); } 
Sign up to request clarification or add additional context in comments.

Comments

2

In your edit, the operators still differ by const qualification. The member function is not const (and thus effectively operates on non-const left-hand-side and const right-hand-side).

These are all ambiguous:

  • No const:
    friend myTime operator+(myTime &t1, myTime &t2); myTime operator+(myTime &ref);

  • Const lhs:
    friend myTime operator+(const myTime &t1, myTime &t2); myTime operator+(myTime &ref) const;

  • Const lhs vs const rhs ("similar conversions"):
    friend myTime operator+(const myTime &t1, myTime &t2); myTime operator+(const myTime &ref);

  • Const rhs vs const lhs ("similar conversions"):
    friend myTime operator+(myTime &t1, const myTime &t2); myTime operator+(myTime &ref) const;

  • Const rhs:
    friend myTime operator+(myTime &t1, const myTime &t2); myTime operator+(const myTime &ref);

  • All const:
    friend myTime operator+(const myTime &t1, const myTime &t2); myTime operator+(const myTime &ref) const;

Not ambiguous: Every distribution of const except the above, i.e. every distribution of const where the functions differ in number of consts.

3 Comments

Thanks for the explanation. I understand now that the functions have different declarations. What is the rule which decides the actual function taken in the non-ambigous case?
@Ranon The rules are the normal rules for overload resolution, which you can find at e.g. eel.is/c++draft/over.match. I would advise against relying on the exact details because if you need to look at the standard to figure it out, everyone else reading your code will have to do the same. Just avoid the ambiguity in the first place.
There is also ambiguity of all the cases you mention if the only difference between two functions is that one accepts a const reference and another accepts an argument of the same type by value. For example, if there is a member myTime operator+(const myTime &) and a member myTime operator+(myTime), then time1 + time2 or time1.operator+(time2) each result in ambiguity.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.