永发信息网

C++中,operator<重载为何可以写在类外面,而在类里为何要加friend?

答案:3  悬赏:20  手机版
解决时间 2021-03-14 20:16
  • 提问者网友:
  • 2021-03-14 13:26
C++中,operator<重载为何可以写在类外面,而在类里为何要加friend?
最佳答案
  • 五星知识达人网友:胯下狙击手
  • 2021-03-14 14:02
重载运算符不需要一定是成员函数,以Person和<运算符为例,下列三种写法都是正确的


//  "a//作为成员函数重载(常见)
class Person{
string name;
int age;
public:
Person(const char* name, int age):name(name),age(age){}
     bool operator<(const Person& b);

};
bool Person::operator<(const Person& b)
{
//作为成员函数时,*this即为左操作数a
...
}

//作为友元函数重载
class Person{
string name;
int age;
public:
Person(const char* name, int age):name(name),age(age){}
     friend bool operator<(const Person& a,const Person& b);

};
bool operator<(const Person& a,const Person& b)
{
...
}

//作为普通函数重载(不推荐)
class Person{
public://注意,重载运算符为普通函数时,使用到的类成员必须为public
string name;
int age;
public:
Person(const char* name, int age):name(name),age(age){}

};
bool operator<(const Person& a,const Person& b)
{
...
}追问不对啊,我上面那个例子,如果作为成员函数,必须要加friend,否则报错。追答如果我没有搞错的话,你给的这段
class Person{
string name;
int age;
public:
Person(const char* name, int age):name(name),age(age){}

       friend  bool operator<(const Person& a,const Person& b){return true;}

};等价于我写的第二种,这个重载并没有作为Person的成员函数,而仅仅是它的友元函数,只不过把函数的内容直接写在了类的里面。作为成员函数重载时,应像我写的第一种写法,不写friend,参数只写一个右操作数,且如果函数定义在外部时要写Person::

追问这不跟你的说法矛盾么,你前面给的例子,operator<作为成员函数不需要加friend,但是这里又加了,而且不能去掉friend。能告诉我这是为何追答我再说一遍,你这么写并不是成员函数,加了friend就不是成员函数,它只不过是写在了类里面,但只要写上friend,它的本质就是一个可以与类私有对象联络的【外部函数】。
至于这里为什么不能去掉friend把它变成成员函数,请参照我写的第一种成员函数的写法,作为成员函数时,其参数必须 只有 一个追问为何一个参数时才能作为成员函数?提问次数有限制了,能留个QQ说说么追答对于Person a,b;
执行abool operator<(const Person&,const Person&);//外部函数重载,可以是friend

bool Person::operator<(const Person&);//成员函数重载
除了这两个之外,你可以定义其它参数形式的重载函数,例如你说的双参数成员函数:
bool Person::operator<(const Person&,const Person&);
但编译器并不会检查到它,编译器只认前两种,而第三种相当于定义了一个无用的重载
还有问题找这个QQ:2451320606
全部回答
  • 1楼网友:酒者煙囻
  • 2021-03-14 15:40
friend 声明该函数是类的友元,可以访问私有成员,用friend可以避免用类名加点调用函数,这比较麻烦,还有friend只能在类内,不能在类外再加,否则会报错追问问题是,作为成员函数时,我上面那个例子,必须要加friend,否则报错,这是为何追答不加friend就是成员函数,你在外面实现时需在函数前加类名::追问在类里面定义不就行了,这不是问题
  • 2楼网友:纵马山川剑自提
  • 2021-03-14 14:12

你可以不那样写,可以把它当作成员函数,加friend后只是为了说明了以下几点:
该函数是外部的一个函数,非类的成员函数
该函数内部使用该类的对象时可以访问该类的私有和保护成员


如果你把重载函数写成成员函数,而且是public属性,对于使用该操作符时其实没有差别,但是如果是保护或者私有,那么在外部你就不能使用该操作符了.以下是例子
class a

{
public:
    bool operator<(const Person& b){return true;}

};


a a1,a2;
bool bRet = a1 < a2 ; 正确


-------------------------------------------------------------------------------------
class a

{
protected:
    bool operator<(const Person& b){return true;}

};


a a1,a2;
bool bRet = a1 < a2 ; 错误


-----------------------------------------------------------------------------------------
class a

{
public:
    friend  bool operator<(const Person& a,const Person& b);//加了friend表示该函数不是成员函数了,顺便说一下 你上面的例子中,既然加了friend就不能再这里实现,所以{ return true;}是错误的写法

};
bool operator<(const Person& a,const Person& b){return true;}



a a1,a2;
bool bRet = a1 < a2 ; 正确


------------------------------------------------------------------------------------------
class a

{
protect:
    friend  bool operator<(const Person& a,const Person& b);
    int a; // 假定下面的操作符要访问 保护成员变量a 如果是保护函数也一样

};
bool operator<(const Person& a,const Person& b){ return a.a > b.a;} //这里访问了保护成员a



a a1,a2;
bool bRet = a1 < a2 ; 错误 因为函数内部访问了 保护成员a
-------------------------------------------------------------------------------------------
class a

{
    friend  bool operator<(const Person& a,const Person& b);// 这里友元了操作符函数
protect:
    int a; // 假定下面的操作符要访问 保护成员变量a 如果是保护函数也一样

};
bool operator<(const Person& a,const Person& b){ return a.a > b.a;} //这里访问了保护成员a



a a1,a2;
bool bRet = a1 < a2 ; 正确,因为该操作符被类a友元了,所以即使内部访问了类的属性也正确追问问题是,作为成员函数时,我上面那个例子,必须要加friend,否则报错,这是为何追答那是因为你的例子写法有问题,至于什么问题,你可以参考我上面的回答.
class a
{
public:
bool operator<(const Person& b){return true;}
};
a a1,a2;
bool bRet = a1 < a2 ; 正确
这个就是不加friend的例子,注意参数,这里是一个,而不是2个
我要举报
如以上回答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
点此我要举报以上问答信息
大家都在看
推荐资讯