Ranon
Ranon

Reputation: 109

Precedence of Friend vs member operator overloading

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?

Upvotes: 0

Views: 232

Answers (2)

Max Langhof
Max Langhof

Reputation: 23681

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.

Upvotes: 2

Michael Mahn
Michael Mahn

Reputation: 797

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();
}

Upvotes: 3

Related Questions