Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 重载相同操作的友元函数和类方法的优先级_C++_Methods_Operator Overloading_Overloading_Friend - Fatal编程技术网

C++ 重载相同操作的友元函数和类方法的优先级

C++ 重载相同操作的友元函数和类方法的优先级,c++,methods,operator-overloading,overloading,friend,C++,Methods,Operator Overloading,Overloading,Friend,这是我的密码: #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() { cou

这是我的密码:

#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;
}
#包括
使用名称空间std;
类有理数
{
私人:
int-num;
int den;
公众:
有理数(inta):num(a),den(1){
有理数(inta,intb):num(a),den(b){
void parse()
{

cout我将提供一个简化视图。为此,您将扮演编译器的角色

假设您正忙于编译一些代码,遇到一个运算符,它被赋予了一个
RationalNumber
和一个
int
作为操作数。该怎么办?好吧,编译器的工作描述包括将运算符与实现相匹配,因此您会抱怨并查看声明列表。您会发现两个可行的选项

  • RationalNumber
    的一个成员,它期望一个
    RationalNumber
    作为它的第二个操作数。这不是一个完美的匹配,但是你可以找到你记得在某处看到的从
    int
    RationalNumber
    的讨厌的转换
  • 一种自由运算符,期望一个
    有理数
    作为其第一个操作数,一个
    int
    作为其第二个操作数。完美匹配
  • 您正忙于编译代码。您确实不想找到这种转换,因此选择#2作为更简单的选项

    事实并不像上面那样轻率,但基本原则是合理的。在编译一个参数列表后,编译器将在声明的参数和提供的参数之间寻找最佳匹配。不严格地说,“最佳”匹配是需要编译器进行最少工作的匹配。(有很多转换使其精确。)精确匹配(提供的参数已经是所需的类型)比其他类型更可取


    在决策过程的这一点上,没有考虑“朋友”和“成员”之间的区别。

    我将提供一个简化的视图。为此,您将扮演编译器的角色

    假设您正忙于编译一些代码,遇到一个运算符,它被赋予了一个
    RationalNumber
    和一个
    int
    作为操作数。该怎么办?好吧,编译器的工作描述包括将运算符与实现相匹配,因此您会抱怨并查看声明列表。您会发现两个可行的选项

  • RationalNumber
    的一个成员,它期望一个
    RationalNumber
    作为它的第二个操作数。这不是一个完美的匹配,但是你可以找到你记得在某处看到的从
    int
    RationalNumber
    的讨厌的转换
  • 一种自由运算符,期望一个
    有理数
    作为其第一个操作数,一个
    int
    作为其第二个操作数。完美匹配
  • 您正忙于编译代码。您确实不想找到这种转换,因此选择#2作为更简单的选项

    事实并不像上面那样轻率,但基本原则是合理的。在编译一个参数列表后,编译器将在声明的参数和提供的参数之间寻找最佳匹配。不严格地说,“最佳”匹配是需要编译器进行最少工作的匹配。(有很多转换使其精确。)精确匹配(提供的参数已经是所需的类型)比其他类型更可取


    在决策过程的这一点上,“朋友”和“成员”之间的区别未查看。

    调用friend函数不需要隐式转换,因此选择它而不是member函数。对这个问题的完整回答需要很多篇幅。TLDR版本是,如果编译器可以调用函数而不转换任何参数,那么它宁愿这样做,而不是调用不转换参数的版本s需要一些转换。如果添加
    RationalNumber运算符/(int),请阅读
    成员函数到
    理性数
    ,您应该得到的错误将表明友元函数或成员函数之间没有偏好。调用友元函数不需要隐式转换,因此选择它而不是成员函数。完整回答此问题需要很多页的密集文章。TLDR版本如果编译器可以在不转换任何参数的情况下调用函数,则它更愿意这样做,而不是调用确实需要一些转换的版本。如果添加
    RationalNumber运算符/(int),请阅读;
    成员函数到
    理性编号
    ,您应该得到的错误将表明友元函数和成员函数之间没有偏好。
    #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;
    }