2

Why am I allowed to do this, why there is no ambiguity complain, and why is the class' method chosen with prior to the other one?

class EX
{
public:
    //...

    void operator+(const EX& ref)
    {
        cout << "A";
    }
};

void operator+(const EX& ref1, const EX& ref2)
{
    cout << "B" << endl;
}

int main()
{
    EX obj1{20};
    EX obj2{30};


    cout << "obj1 + obj2 = " <<  obj1 + obj2 << endl;

    return 0;
}

I was expecting the global function operator+ to be called an "B" printed on the screen, instead "A" was printed.

Cătălina Sîrbu
  • 1,253
  • 9
  • 30

1 Answers1

6

Your member overload accepts only non-const instances of EX for the first operand while the free overload accepts both const and non-const instances. By overload resolution rules, the non-const wins out because it exactly matches the type being passed in.

You'll get an ambiguity error if you make the member overload const, indicating that *this is const:

void operator+(const EX& ref) const
{
    cout << "A";
}
chris
  • 60,560
  • 13
  • 143
  • 205
  • thank you for the answer. Why is my member overload accepting only non-const instances of `EX` ? – Cătălina Sîrbu Apr 13 '20 at 20:34
  • @CătălinaSîrbu, That's the default behaviour. – chris Apr 13 '20 at 20:34
  • could you please provide a link for further reading regarding `overload resolution rules` and `default behavior for overload member function?` – Cătălina Sîrbu Apr 13 '20 at 20:39
  • @CătălinaSîrbu, Overload resolution is a big one. [This reference](https://en.cppreference.com/w/cpp/language/overload_resolution) covers a lot of detail, but I haven't seen much in the way of blog posts about the subject. I'm not sure what the exact rule is for operators, where you're dealing with both free and member functions at the same time, but it's likely fairly consistent with the individual rules there. If you have a const member function and a non-const one, using a non-const object calls the non-const one (think overloading an array subscript with `a[b] = 5` support). – chris Apr 13 '20 at 20:51
  • For free functions, there's a rule saying that if you're binding a parameter reference to a non-const argument of the same type, a non-const reference is a better match than a const one (it might even be considered an exact match depsite the reference layer, but I don't remember). There's not much reason for operator rules that mix these to be inconsistent with them. As for default behaviour, that part has nothing to do with overloading. By default, all member functions are non-const. If you try to call them on a const object, it won't work until you make them const. – chris Apr 13 '20 at 20:54
  • You can refer to more information about that last point [in this question](https://stackoverflow.com/questions/751681/meaning-of-const-last-in-a-function-declaration-of-a-class). – chris Apr 13 '20 at 20:55