友元和类的关系还可以更复杂。

举个例子,假设出现了交互式遥控器,交互式遥控器能够让您回答电视节目中的问题,如果回答错误,电视将在控制器上产生嗡嗡声。

这个例子的问题,可以使用新的友元关系来解决。我把它叫做相互的友情。

即一些Remote方法能够像前面那样访问Tv对象,而一些Tv方法也能影响Remote对象。

这可以通过让类彼此成为对方的友元来实现。即相互的友元

即除了Remote是Tv的友元外,Tv还是Remote的友元。

这里对于使用Remote对象的Tv方法,其原型可以再Remote方法类声明之前声明,但必须在Remote声之后定义,以便编译器有足够的信息来编译该方法。

方法如下:(两个类互为友元类)

class Tv

{

friend class Remote;

public:

  void buzz(Remote & r);

  ...

};

class Remote

{

friend class Tv;

public:

  void Bool volup(Tv & t) {t.volup();}

}

//buzz方法的声明和定义是分开的,定义要在Remote声明之后,这是因为这个时候编译器编译该方法时,知道Remote指的是什么了;

inline void Tv::buzz(Remote & r)

{

...

}

还有一种友元的情况是共同的友元

需要使用友元的另一种情况是,函数需要访问两个类的私有数据。

从逻辑上看,这样的函数时每个类的成员函数,但是这是不可能的。

它可以是一个类的成员,同时是另一个类的友元,但有时将函数作为两个类的友元更加合理。

例如,假定有一个Probe类和一个Analyzer类,前者表示某种可编程的测量设备,后者表示某种可编程的分析设备。

这两个类中都有内部时钟,且希望它们能够同步,则应包含下述代码行:

 class Analyzer   //forward declaration
class Probe
{
friend void sync(Analyzer & a, const Probe & p); // sync a to p
friend void sync(Probe & p, const Analyzer & a); // sync p to a
...
} class Analyzer
{
friend void sync(Analyzer & a, const Probe & p); // sync a to p
friend void sync(Probe & p, const Analyzer & a); // sync p to a
...
} //define the friend functions
inline void sync(Analyzer & a, const Probe & p)
{
...
} inline void sync(Probe & p, const Analyzer & a)
{
...
}

前向声明使得编译器看到Probe类声明中的友元声明时,知道Analyzer是一种类型。

关于友元的总结:

理解友元的产生和意义,首先要从类说起;

类对象的私有和保护数据成员只能通过类的公有方法访问。(这里暂时不讨论类的继承)

这样做的好处是提高了数据的安全性和封装性,接口简洁。

但是这种对数据的访问和修改的强限制手段,有时候会在某些场景下不方便。

有些情况可能需要直接去访问或修改类的私有数据成员。那么为了提高类修改私有数据的灵活性,引入友元的概念。

举个例子:假如你把一个人定义成朋友,那么这个朋友也获得了进出你家的资格,而不仅仅是你的家人。

但是你的朋友不是你的家人,是有别于你的家人。所以友元不是类的成员

友元可以是函数,类的成员函数,甚至类;

其实还可以这样理解:把友元看成与类方法一样都是表达类接口的一种方式。

最新文章

  1. 《笨办法学C》笔记之基础语法
  2. JavaScript Patterns 6.2 Expected Outcome When Using Classical Inheritance
  3. 【HDU】1814 Peaceful Commission
  4. 16位的MD5加密和32位MD5加密的区别
  5. u163是什么故障 佳能MX328 u163是什么意思?墨水打完了,我加了墨水后还是显示U163(请检查墨水-彩色)警告灯亮
  6. [Everyday Mathematics]20150131
  7. [Codeforces Round #296 div2 D] Clique Problem 【线段树+DP】
  8. 【刷题 Python Tip】题目6~10
  9. Cramfs、JFFS2、YAFFS2的全面对比
  10. c++,static 静态成员变量 / 静态成员函数
  11. 移动WEB开发资源
  12. android6.0搜索蓝牙无法显示问题解决
  13. Mysql-表的完整性约束
  14. SpringBoot之Swagger2
  15. Redhat学习(此为草稿,正式笔记之后存放)
  16. AspNetCore2 Hangfire定时任务
  17. Mysql for Linux安装配置之—— 源码安装
  18. 空指针、NULL指针、零指针
  19. Python爬虫爬取贴吧的帖子内容
  20. R绘图 第八篇:绘制饼图(ggplot2)

热门文章

  1. ISAP网络流算法
  2. Leetcode:Two Sum分析和实现
  3. spring 框架jdbc连接数据库
  4. Linux设置串口波特率等参数
  5. Linux内核的特征
  6. Solidity transfer vs send 区别
  7. 基于 EntityFramework 的数据库主从读写分离架构 - 目录
  8. linux信号基本概念及如何产生信号
  9. [原创]Java中使用File类的list方法获取一定数量的文件:FilenameFilter接口的特殊用法
  10. windows phone 8 新增功能:从一个应用程序启动另一个程序(file association 和 Protocol association两种方式)