C++中,operator<重载为何可以写在类外面,而在类里为何要加friend?
using namespace std;
#include <string>
#include <algorithm>
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;}
};
bool operator<(const Person& a,const Person& b){return true;}
//就在这里,重载不是要成员函数才行么,这里operator他跟类完全没有关系啊,是一个独立的函数啊,为何类在<会去调用它?
//还有,为何写在类里,变成成员函数时,要加friend?
//还有,如果有operator=,那这个类成员函数就不用加friend,同样是运算符重载,为何这个又不用加firend?
int main()
{
Person d[3]= {Person("芙蓉",18),Person("杨强",20),Person("薇薇",16)};
sort(d,d+3);
return 0;
} 展开
重载运算符不需要一定是成员函数,以Person和<运算符为例,下列三种写法都是正确的
// "a<b"的重载的三种方法
//作为成员函数重载(常见)
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::
你可以不那样写,可以把它当作成员函数,加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个
问题是,作为成员函数时,我上面那个例子,必须要加friend,否则报错,这是为何
不加friend就是成员函数,你在外面实现时需在函数前加类名::