为了在类之间进行数据共享时,提高效率,C++引入了友元的概念。友元主要有三个方面的应用:

  1. 将普通函数声明为类的友元函数;
  2. 将一个类声明为其他类的友元类;
  3. 将一个类中的成员函数声明为其他类的友元函数。

下面分别介绍。

1、普通函数声明为友元函数

将一个普通函数,声明为某个类的友元函数后(在函数声明前加上“friend”关键字),该函数就可以访问类中的任何成员。观察下面的代码:

#include<iostream>
using namespace std;class friend_test{private:int a=3;        //非静态成员变量static int b;   //声明静态成员变量public:friend void friend_func(friend_test &f);    //将函数friend_func()函数,声明为该类的友元函数。由于友元函数没有this指针
};
int friend_test::b=4;   //定义静态成员变量//friend_func()函数的实现
void friend_func(friend_test &f)
{cout<<"访问基础类friend_test的私有成员变量:   "<<f.a<<endl;cout<<"访问基础类friend_test的静态成员变量:   "<<friend_test::b<<endl;cout<<"访问基础类friend_test的静态成员变量:   "<<f.b<<endl;
}int main()
{friend_test f;    //声明friend_test类的对象friend(f);        //程序运行正常,按预期输出结果return 0;
}

从上面的程序中可以看出,友元函数访问类的成员变量时,有以下特点:

  1. 访问静态static成员时,可以通过”类名::变量名”和”对象名::变量名”方式访问;
  2. 访问非静态成员时,只能通过“对象名::变量名”方式访问。

2、友元类

若将类A 声明为类B的友元类,那么类A中的所有成员函数都可以访问类B中的所有成员;反之,不成立,即友元不是双向的
观察下面的代码:

#include<iostream>
using namespace std;class A;
class B{public:friend class A;    //声明类A为类B的友元类private:int b;
};
class A{public:void func1(B &BB);  //声明类A的成员函数void func2(B &BB);
};
void A::func1(B &BB)
{cout<<"访问类B的成员变量:   "<<BB.b<<endl;
}
void B::func2(B &BB)
{cout<<"本函数用不到类B的成员变量"<<endl;
}
int main()
{A AA;         //声明类A的对象B BB;         //声明类B的对象A.func1(BB);   //调用类A的成员函数,在成员函数中访问类B的成员变量A.func2(BB);
}

通过以上代码,可以发现类A为类B的友类,类A中所有的成员函数都可以访问类B中的所有成员。那么,此时会带来一个问题,若类A中的某个函数如上面的“func2()”不需要访问类B的成员变量,只有函数“func1()”需要访问类B的成员。
由于友元的引入本来就破坏了“封装”,使得面向对象的颜面有点受损。那么,可以仅仅设置类A的成员函数func1()为类B的友元函数,从而类B的成员对函数“func2()”就不可见了^-^

上面所述就是将类的成员函数声明为其他类的友元函数的目的。

3、类的成员函数声明为其他类的友元函数

正如上面所说,若将类A的某个成员函数”func_A()”声明为类B的友元函数后,函数”func_A”就可以访问类B中的所有成员。
观察下面的例子:

#include<iostream>
using namespace std;class B;
class A{public:void func_A(B &BB);  //类A的成员函数void func();
};
//类A的成员函数实现
void A::func()
{cout<<"我只是个普通的宝宝~~~"<<endl;
}
class B{public:friend void A::func_A(B &BB);  //将类A的func_A()成员函数声明为类B的友元private:int b=5;                      //类B的成员变量
};
//类A中为类B友元的成员函数实现,必须放在类B定义之后
void A::func_A(B &BB)
{cout<<"通过类A的成员函数访问类B的成员变量:   "<<BB.b<<endl;
}
int main()
{A AA;        //类A的对象B BB;       //类B的对象A.func();    //访问类A的成员函数A.func_A();  //访问类A的成员函数,为类B的友元
}

通过以上分析,将友元的特点总结如下:

  1. 由于友元函数没有this指针,访问静态static成员时,可以通过”类名::变量名”和”对象名::变量名”方式访问;
  2. 访问非静态成员时,只能通过“对象名.变量名”方式访问。
  3. 虽能提高效率,但破坏了程序的封装,尽量减少friend的使用;
  4. 在声明类的成员函数为其他类的友元时,函数实现要放在其他类的定义之后。

C++基础知识友元friend、友元函数和友元类相关推荐

  1. C++:C++语言入门级基础知识考察点回顾之函数、结构体和类

    C++:C++语言入门级基础知识考察点回顾之函数.结构体和类 目录 C++的函数 1.函数的定义.调用,全局变量局部变量 1.1.自定义函数求其倒数

  2. [Python图像处理] 一.图像处理基础知识及OpenCV入门函数

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  3. python程序如何执行死刑_「Python基础知识」Python生成器函数

    原标题:「Python基础知识」Python生成器函数 对于程序而言,内存也是很重要的,因为程序中很多数据都是保存在内存中的,如果内存中存储的数据过多,那么系统就会崩溃,这是人们不希望发生的. 可以采 ...

  4. convert.todatetime指定日期格式_SQL基础知识V2——常用日期函数

    点击上方SQL数据库开发,关注获取SQL视频教程 SQL专栏 SQL数据库基础知识汇总 SQL数据库高级知识汇总 日期函数是数据库中经常需要使用到的,本期将常用的几个日期函数给小伙伴做详细的介绍. G ...

  5. 计算机单招基础知识试题,高职单招《计算机类专业基础知识》正式试卷

    高职单招<计算机类专业基础知识>正式试卷 20XX年高考<计算机类专业基础知识>试卷 一. 单项选择题(在每小题的四个备选答案中,选出一个正确答案,并将正确回答的序号填在题干的 ...

  6. C++_类和对象_对象特性_友元_成员函数做友元---C++语言工作笔记054

    然后我们接着看友元,这次我们来看这个类的成员函数来做友元函数. 还是直接去看例子吧. 写个GoodGay这个类,然后里面有 构造方法,声明一个,Building 这个类的指针,building. 因为 ...

  7. decode函数python在哪里_Python基础知识——encode和decode函数

    以前我们介绍过,Python2.x中默认的编码的基础类型是unicode编码的类型,在Python3.x才转化为基于unicode的字符串. 那么我们在Python2.x的学习中就会遇到各种各样的编码 ...

  8. C++_类和对象_对象特性_友元_全局函数做友元_在类中声明友元权限的全局函数来访问_类中的private权限的变量---C++语言工作笔记052

    然后我们再来看友元,友元,其实就类似于, 比如一个建筑类,这里面有,客厅有卧室, 那么客厅是public的,大家都能访问,但是卧室是private的,外人不能访问 但是,如果是我的朋友,.我想让他访问 ...

  9. 【Python培训基础知识】Python生成器函数

    对于程序而言,内存也是很重要的,因为程序中很多数据都是保存在内存中的,如果内存中存储的数据过多,那么系统就会崩溃,这是人们不希望发生的. 可以采用生成器推导式来解决内存不足的问题.例如,利用生成器推导 ...

  10. 基础知识——用户输入和函数(五)

    基础点 用户输入:message=input("用户输入:") 函数传递列表参数,并且禁止修改列表:列表为a,函数为func(),调用func(a[:]),此时传递的是列表a的副本 ...

最新文章

  1. CopyOnWriteArrayList实现原理及源码分析
  2. Javascript中的深拷贝和浅拷贝
  3. 利用反射,泛型,静态方法快速获取表单值到Model。
  4. spark 2.4.5 简单使用
  5. mongoDB 从单节点迁移到分布式集群 遇到的问题
  6. 【CodeForces - 438D】The Child and Sequence(线段树区间取模操作)
  7. linux错误自动报告工具,linux – 关闭abrt的电子邮件通知(自动错误报告工具)
  8. 华为 招聘 状态 查看_英特尔放弃5G芯片研发:三星受益;爱立信2019年Q1净利润约2.51亿美元;华为也将要与高通和解;天津首个5G电话成功打通...
  9. Add_List2Dictionay
  10. AVR系列之TWI功能测试
  11. linux mv复制命令,linux中删除复制移动文件rm,mv,cp命令详解linux操作系统 -电脑资料...
  12. 学python买什么书-关于 Python 的经典入门书籍有哪些?
  13. 个人用户上网需要有计算机电话线,个人用户上网需要有计算机、电话线、用户账号和口令,以及______。...
  14. office图标显示异常和新建时图标没有显示等问题解决
  15. Linux查看cuda版本
  16. “神舟八号”飞船将瞄准11月1日5时58分发射
  17. 苹果手表支持心电图功能,可能还是逃不过噱头的命运
  18. win10装的AutoCAD 2012版,右上角最小化不显示的解决办法
  19. Airbnb短租数据分析报告
  20. 研究生被导师嫌弃是种怎样的体验?写的太真实了...

热门文章

  1. sharepoint 2013基于AD的Form表单登录(三)——选择用户时,屏蔽掉AD。
  2. 编译Ngnix遇到的问题,查看程序依赖的库文件
  3. 园区网VLAN应用实例
  4. linux 笔记之一mysql源码包安装
  5. 学成在线--23.课程图片管理(上传图片)
  6. 调整标志位方法oracle,面试题(二)(示例代码)
  7. 光源时间_缩短背光源的使用寿命的原因
  8. mysql中如何把两个查询结果列数不同并成一张表_MySQL
  9. JDBC笔记-李伟杰版
  10. 计算机表格复制粘贴后不变,excel表格复制粘贴后格式不变