简体   繁体   中英

Priority of friend function and class method that overload the same operation

Here is my code:

#include <iostream>
using namespace std;

class RationalNumber
{
private:
    int num;
    int den;
public:

    RationalNumber(int a):num(a),den(1){}

    RationalNumber(int a, int b):num(a),den(b){}

    void parse()
    {
        cout << num << "\\" << den << endl;
    }
    
    RationalNumber operator/(RationalNumber);
};

RationalNumber  RationalNumber:: operator/(RationalNumber b)
    {
        return RationalNumber(num * b.den, den * b.num);
    }

int main()
{
    RationalNumber a(1,2);
    int c = 5;
    (a/c).parse();
    return 0;
}

I have a method that overloads "/" operation for my class and returns correspondent object of "RationalNumber".

Also I have a constructor that allows me to initialize my object with integer variable. That is, I can use my overloaded "/" operation for RationalNumber object and integer variable, so the result of my program is 1/10.

But then I add a few lines to my code:

#include <iostream>
using namespace std;

class RationalNumber
{
private:
    int num;
    int den;
public:

    RationalNumber(int a):num(a),den(1){}

    RationalNumber(int a, int b):num(a),den(b){}

    void parse()
    {
        cout << num << "\\" << den << endl;
    }
    
    RationalNumber operator/(RationalNumber);
    friend RationalNumber operator/(RationalNumber, int);
};

RationalNumber  RationalNumber:: operator/(RationalNumber b)
    {
        return RationalNumber(num * b.den, den * b.num);
    }

RationalNumber operator/(RationalNumber v, int n )
    {
        return RationalNumber(0,0);
    }
int main()
{
    RationalNumber a(1,2);
    int c = 5;
    (a/c).parse();
    return 0;
}

I have added a friend function that also overloads "/" operation, receives "RationalNumber" object and integer number, and returns 0/0 - "RationalNumber" object.

So now c in the expression a/c can be treated as the second parameter in my friend function - or as "RationalNumber" object initialized with integer value by one of my constructors. And now the result of the program is 0/0 - that is, the compiler referred to friend function, not to the method, and I wonder why. Is there any defined priority for such cases?

I'll present a simplified view. For this, you will play the role of the compiler.

Suppose you are busy compiling some code and come across an operator that was given a RationalNumber and an int as operands. What to do? Well, the compiler's job description includes matching operators to implementations, so you grumble and look through your list of declarations. You find two viable options.

  1. A member of RationalNumber that expects a RationalNumber as its second operand. This is not a perfect match, but you could find that pesky conversion from int to RationalNumber that you remember seeing somewhere.
  2. A free operator that expects a RationalNumber as its first operand and an int as its second. Perfect match!

You're busy compiling code. You really don't want to find that conversion, so you choose #2 as the easier option.

The reality is not as flippant as the above, but the underlying principle is sound. After compiling a list of viable functions , the compiler will look for the best match between declared parameters and supplied arguments. Loosely speaking, the "best" match is the one that requires the least work by the compiler. (There is a ranking of conversions that makes this precise.) An exact match – the supplied argument is already the needed type – is preferred to everything else.

At this point in the decision-making process, the distinction between "friend" and "member" is not looked at.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM