-
Notifications
You must be signed in to change notification settings - Fork 4
Description
友元
[toc]
友元
C++ 提供了另外一种形式的访问权限:友元。友元有3种:
- 友元函数
- 友元类
- 友元成员函数
通过让函数成为类的友元,可以赋予该函数与类的成员函数相同的访问权限。
为何需要友元
> 在为类重载二元运算符时(带两个参数的运算符)常常需要友元。将 Time 对象乘以实数就属于这种情况。
下面的语句:
A = B * 2.75;将被转换成:
A = B.operator*(2.75);但下面的语句又如何呢?
A = 2.75 * B;从概念上说,2.75*B 与 B*2.75 相同,但第一个表达式不对应于成员函数,因为2.75不是 Timer 类型的对象。记住,左侧的操作数应是调用对象,但2.75不是对象。因此,编译器不能使用成员函数调用来替换该表达式。
解决这个难题的一种方式是,告知每个人(包括程序员自己),只能按 B*2.75 的格式编写,不能写成2.75*B。这是一种对服务器友好-客户警惕的(server-friendly, client-beware)解决方案,与OOP无关。
当然,上述的问题也有解决方案——非成员函数。非成员函数不是由对象调用的,它使用的所有值(包括对象)都是显式参数。这样,编译器能够将下面的表达式:
A = 2.75 * B;与下面的非成员函数调用匹配:
A = operator*(2.75,B);该函数的原型如下:
Time operator*(double m, const Time &t);对于非成员重载运算符函数来说,运算符表达式左边的操作数对应于运算符函数的第一个参数,运算符表达式右边的操作数对应于运算符函数的第二个参数。而原来的成员函数可以访问类的私有成员,它们被称为友元函数。
创建友元
创建友元函数的第一步是将其原型放在类声明中,并在原型声明前加上关键字 friend:
friend Time operator*(double m, const Time & t);该原型意味着下面两点:
- 虽然
operator*()函数是在类声明中声明的,但它不是成员函数,因此不能使用成员运算符来调用; - 虽然
operator*()函数不是成员函数,但它与成员函数的访问权限相同。
第二步是编写函数定义。因为它不是成员函数,所以不要使用 Time:: 限定符。另外,不要在定义中使用关键字 friend,定义如下:
Time operator*(double m,const Tlme & t)// frlend not ued in definition
{
Time result;
long totalminutes = t.hours * m * 60 + t.minutes * m;
result.hours = totalminutes/60;
result.minutes = totalminutes % 60;
return result;
}总之,类的友元函数是非成员函数,其访问权限与成员函数相同。
blog link [友元](https://holdyounger.github.io/立志博览群书/《C++ primer plus》/第11章 使用类/友元/)