C++ Primer Plus读书笔记 ——— 11.3 友元 15.1 友元

友元的角色

根据OOP的数据隐藏原则, 一个类的私有数据只有通过给定的公有接口才能去访问。
最常用的公有接口就是类的公共成员方法。
但是这种访问方式局限性太多,在很多时候不适合解决特定的问题。
于是友元提供了另一种共有接口。
赋予一个类外的函数和这个类的成员函数相同的访问权限。

思考:
使用友元是否破坏了OOP的数据隐藏规则?根据前面的分析,发现并没有,友元只是提供了另一种访问类数据的接口罢了,它的地位和公共的成员函数几乎相同
其次,友元函数的数目是在类内声明的,而不是类外,所以不会出现类外声明友元函数然后私自调用类内的数据的风险。
相反,在类内声明友元函数,接口的开放与否仍然是由编写类的程序员决定,这再次体现了“它的地位和公共的成员函数相同,是提供了另一种访问类数据的接口罢了”这句话。
总之,类的友元函数是非成员函数,它的访问权限和成员函数相同。

友元的分类

友元(普通)函数
友元成员函数
友元类

友元函数的声明与定义

第一步:在类里面声明友元函数的原型,必须加上friend修饰。
第二步: 在类外编写函数定义(当然作为内联的也可以)。注意,前面既不加friend修饰,也不加类::限定符修饰。

例如:

class A{
    
    
	friend int func(int,int);
};
int func(int x,int y){
    
    
}
  • 友元声明的位置
    友元声明放置在共有、私有、保护的位置都无关紧要。

  • 友元类
    不仅仅函数可以作为一个类的友元,一整个类也可以作为另一个类的友元。这个时候,作为友元的类的所有成员函数都拥有原始类的数据访问权限。

使用友元类

举书上的例子,遥控器与电视机的关系。
记电视机类为Tv类,遥控器类为Remote类。
首先遥控器并不是电视机一部分,所以不能进行类的组合。
其次,一个遥控器可以控制多个电视机,一个电视机也可以由多个遥控器控制。
所以用一个大类去包含Remote类和Tv类是不合适的。
最后,遥控器要可以控制电视机的状态参量。

如果要想访问Tv的私有数据,要么将这些个私有数据全部提供对外的接口以供访问(这样明显感觉操作过于局限化),要么将Remote的成员函数都作为Tv的成员函数(麻烦)。

于是,类友元的做法就产生了。

友元成员函数

不同于将一整个类作为某个类的友元,友元成员函数指的是将一个类的某些成员函数作为另一个类的友元

这样做的含义没什么不清楚的。但是这时,必须小心排列各种声明和定义的顺序。

以书上的例子为例:

class Tv; // 前置声明
class Remote{
    
        //友元
	……
	void set_chan(Tv& t);
	……
};
class Tv{
    
    
	int channel;
	……
	friend void Remote::set_chan(Tv&,int); //friend前缀表明它是友元、类域限定符表示它是某个类的成员函数
	……
};

void Remote::set_chan(Tv& t,int c){
    
    
	t.channel = c;
}

互为友元

如果两类互相依赖对方的信息,不适合合并成一个大类,可以考虑将将它们互为对方的友元类。

共同的友元

如果两个函数需要同时访问两个类的私有数据,同时将它置为这两个类的成员函数是不可能的。
作为一个类的成员函数,作为另一个类的友元函数虽然可以,但不一定合理(不对称)。
这个时候,将它都作为这两个类的友元函数就是一种比较好的做法。

猜你喜欢

转载自blog.csdn.net/qq_44846324/article/details/108113403
今日推荐