文章目录

  • 1 全局函数做友元
  • 2 类做友元
  • 3 成员函数做友元

生活中你的家有客厅(public),有你的卧室(private)
客厅所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去

但是呢,你也可以允许 隔壁老王 进去。

在程序里,有些私有属性 也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术

友元的目的 就是让一个函数或者类 访问另一个类中的私有成员

友元的关键字为 friend

友元的三种实现

  • 全局函数做友元
  • 类做友元
  • 成员函数做友元

1 全局函数做友元

首先,我们要定义一个房屋类,公共成员变量为客厅,私有成员变量为卧室

class Building
{// Building的构造函数,给成员变量赋初值Building(){m_SittingRoom = "客厅";m_BedRoom = "卧室";}string m_SittingRoom;  // 客厅private:string m_BedRoom;      // 卧室
};

然后定义一个全局函数 laoWang(),用来访问Building类中的私有成员

void laoWang1(Building *building)
{cout << "隔壁老王 全局函数 正在访问:(地址传递) " << building->m_SittingRoom << endl;cout << "隔壁老王 全局函数 正在访问:(地址传递) " << building->m_BedRoom << endl;
}

当然也可以用引用传递或者最简单的值传递

void laoWang2(Building &building)
{cout << "隔壁老王 全局函数 正在访问:(引用传递) " << building.m_SittingRoom << endl;cout << "隔壁老王 全局函数 正在访问:(引用传递) " << building.m_BedRoom << endl;
}void laoWang3(Building building)
{cout << "隔壁老王 全局函数 正在访问:( 值传递 ) " << building.m_SittingRoom << endl;cout << "隔壁老王 全局函数 正在访问:( 值传递 ) " << building.m_BedRoom << endl;
}

最后定义一个测试函数test(),实现 laoWang() 这个全局函数做友元访问类的私有成员

void test()
{Building building;laoWang1(&building);laoWang2(building);laoWang3(building);
}

但是,现在还不能实现全局函数访问类的私有成员!

关键代码

friend void laoWang1(Building *building);
friend void laoWang2(Building &building);
friend void laoWang3(Building building);

在Building类中声明友元函数,告诉编译器 laoWang全局函数是 Building类 的好朋友,可以访问Building对象的私有成员

class Building
{// 告诉编译器 laoWang全局函数是 Building类  的好朋友,可以访问Building对象的私有成员friend void laoWang1(Building *building);friend void laoWang2(Building &building);friend void laoWang3(Building building);public:Building(){m_SittingRoom = "客厅";m_BedRoom = "卧室";}string m_SittingRoom; // 客厅private:string m_BedRoom;      // 卧室
};

下面给出全局函数做友元访问类的私有成员的完整示例代码

#include <iostream>
#include <string>using namespace std;// 房屋类
class Building
{// 告诉编译器 laoWang全局函数是 Building类  的好朋友,可以访问Building对象的私有成员friend void laoWang1(Building *building);friend void laoWang2(Building &building);friend void laoWang3(Building building);public:Building(){m_SittingRoom = "客厅";m_BedRoom = "卧室";}string m_SittingRoom; // 客厅private:string m_BedRoom;      // 卧室
};//全局函数
void laoWang1(Building *building)
{cout << "隔壁老王 全局函数 正在访问:(地址传递) " << building->m_SittingRoom << endl;cout << "隔壁老王 全局函数 正在访问:(地址传递) " << building->m_BedRoom << endl;
}void laoWang2(Building &building)
{cout << "隔壁老王 全局函数 正在访问:(引用传递) " << building.m_SittingRoom << endl;cout << "隔壁老王 全局函数 正在访问:(引用传递) " << building.m_BedRoom << endl;
}void laoWang3(Building building)
{cout << "隔壁老王 全局函数 正在访问:( 值传递 ) " << building.m_SittingRoom << endl;cout << "隔壁老王 全局函数 正在访问:( 值传递 ) " << building.m_BedRoom << endl;
}void test()
{Building building;laoWang1(&building);laoWang2(building);laoWang3(building);
}int main()
{test();
}

输出结果

隔壁老王 全局函数 正在访问:(地址传递) 客厅
隔壁老王 全局函数 正在访问:(地址传递) 卧室
隔壁老王 全局函数 正在访问:(引用传递) 客厅
隔壁老王 全局函数 正在访问:(引用传递) 卧室
隔壁老王 全局函数 正在访问:( 值传递 ) 客厅
隔壁老王 全局函数 正在访问:( 值传递 ) 卧室

2 类做友元

首先,声明一个要访问的私有变量所属的Building类,防止在下面的好LaoWang类中,编译器不认识Building(当然也可以采取先定义Building类,再定义隔壁老王LaoWang类,这样就不用声明Building类了)

class Building;

然后定义一个隔壁老王LaoWang类,声明了一个Building类型的指针变量building。其中,成员函数采用另一种方式:类内声明,类外定义,可以简化类的内容(在全局函数做友元的示例中,采用在类内声明并定义成员函数的方式,两种方式均可)

class LaoWang
{public://LaoWang的构造函数LaoWang();void visit();    //参观函数  访问Building中的属性Building * building;private:};

接着给出Building类的定义

class Building
{public://Building的构造函数类内声明,在类外定义Building();string m_SittingRoom; // 客厅private:string m_BedRoom;      // 卧室};

下面给出类外定义成员函数,需要注意的是,在类外定义,需要在成员函数加上所在类的作用域(类名::成员函数名()),以便于告诉编译器,该成员函数属于哪个类。

//Building类的构造函数
Building::Building()
{m_SittingRoom = "客厅";m_BedRoom = "卧室";cout << m_SittingRoom << endl;cout << m_BedRoom << endl;}//LaoWang的构造函数
LaoWang::LaoWang()
{// 创建建筑物对象building = new Building;    //在堆区开辟一块内存,并赋给building指针}//LaoWang的成员函数visit()
void LaoWang::visit()
{cout << "隔壁老王类正在访问:" << building->m_SittingRoom << endl;cout << "隔壁老王类正在访问:" << building->m_BedRoom << endl;
}

最后定义一个测试函数,实现类做友元访问其他类的私有成员

void test()
{LaoWang lw //定义一个LaoWang类的对象;lw.visit();
}

但是,现在还不能实现一个类访问另一个类的私有成员!

关键代码

friend class LaoWang;

在Building类中声明一个友元类,告诉编译器 LaoWang类是 Building类 的好朋友,可以访问Building对象的私有成员

class Building
{// 告诉编译器,LaoWang类是Building类的好朋友,可以访问Building类的私有成员friend class LaoWang;
public:Building();string m_SittingRoom; // 客厅private:string m_BedRoom;      // 卧室};

下面给出类做友元实现一个类访问另一个类私有成员的完整示例代码

#include <iostream>
#include <string>using namespace std;// 类作友元class Building;
class LaoWang
{public:LaoWang();void visit();  //参观函数  访问Building中的属性Building * building;private:};// 房屋类
class Building
{// 告诉编译器,LaoWang类是Building类的好朋友,可以访问Building类的私有成员friend class LaoWang;
public:Building();string m_SittingRoom; // 客厅private:string m_BedRoom;      // 卧室
};// 类外定义成员函数Building::Building()
{m_SittingRoom = "客厅";m_BedRoom = "卧室";
}LaoWang::LaoWang()
{// 创建建筑物对象building = new Building;
}void LaoWang::visit()
{cout << "隔壁老王LaoWang类正在访问:" << building->m_SittingRoom << endl;cout << "隔壁老王LaoWang类正在访问:" << building->m_BedRoom << endl;
}void test()
{LaoWang lw;lw.visit();
}int main()
{test();return 0;
}

输出结果

隔壁老王LaoWang类正在访问:客厅
隔壁老王LaoWang类正在访问:卧室

3 成员函数做友元

类似于类作友元,我们首先声明一个Building类,防止在下面的好LaoWang类中,编译器不认识Building

class Building;

然后定义LaoWang类,同样采用成员函数在类内声明,类外定义的方式。其中定义两个访问函数

  • visit1(),可以 访问Building中的私有成员
  • visit2(),不可以 访问Building中的私有成员
class LaoWang
{public:LaoWang();void visit1(); //让visit1()函数   可以 访问Building中的私有成员void visit2();   //让visit2()函数 不可以 访问Building中的私有成员Building *building;private:};

下面给出Building类的定义

class Building
{public:Building();string m_SittingRoom; //客厅private:string m_BedRoom;       //卧室
};

下面给出类外定义成员函数

//LaoWang类的构造函数
LaoWang::LaoWang()
{building = new Building;
}//LaoWang类的成员函数visit1()
void LaoWang::visit1()
{cout << "隔壁老王LaoWang类中的visit1()函数正在访问:" << building->m_SittingRoom << endl;cout << "隔壁老王LaoWang类中的visit1()函数正在访问:" << building->m_BedRoom << endl;
}//LaoWang类的成员函数visit2()
void LaoWang::visit2()
{cout << "隔壁老王LaoWang类中的visit2()函数正在访问:" << building->m_SittingRoom << endl;//cout << "隔壁老王LaoWang类中的visit2()函数正在访问:" << building->m_BedRoom << endl;   //错误!私有属性不可访问
}//Building类的构造函数
Building::Building()
{m_SittingRoom = "客厅";m_BedRoom = "卧室";
}

最后用一个测试函数实现成员函数做友元实现对另一个类私有成员的访问

void test()
{LaoWang lw;lw.visit1();lw.visit2();
}

同样的,现在还没有声明友元,因此类中的成员函数还不能访问另一个类的私有成员

关键代码

friend void LaoWang::visit1();

在Building类中声明一个友元成员函数,告诉编译器 **visit1()**成员函数是 Building类 的好朋友,可以访问Building对象的私有成员

class Building
{// 告诉编译器,LaoWang类下的visit1()函数是Building类的好朋友,可以访问Building的私有成员friend void LaoWang::visit1();public:Building();string m_SittingRoom;   //客厅private:string m_BedRoom;       //卧室
};

下面给出成员函数做友元实现一个类的成员函数访问另一个类私有成员的完整示例代码

#include <iostream>
#include <string>using namespace std;class Building;class LaoWang
{public:LaoWang();void visit1(); //让visit1()函数   可以 访问Building中的私有成员void visit2();   //让visit2()函数 不可以 访问Building中的私有成员Building *building;private:};class Building
{// 告诉编译器,LaoWang类下的visit1()函数是Building类的好朋友,可以访问Building的私有成员friend void LaoWang::visit1();public:Building();string m_SittingRoom;   //客厅
private:string m_BedRoom;       //卧室
};LaoWang::LaoWang()
{building = new Building;
}void LaoWang::visit1()
{cout << "隔壁老王LaoWang类中的visit1()函数正在访问:" << building->m_SittingRoom << endl;cout << "隔壁老王LaoWang类中的visit1()函数正在访问:" << building->m_BedRoom << endl;
}void LaoWang::visit2()
{cout << "隔壁老王LaoWang类中的visit2()函数正在访问:" << building->m_SittingRoom << endl;//cout << "隔壁老王LaoWang类中的visit2()函数正在访问:" << building->m_BedRoom << endl;   //错误!私有属性不可访问
}Building::Building()
{m_SittingRoom = "客厅";m_BedRoom = "卧室";
}void test()
{LaoWang lw;lw.visit1();lw.visit2();
}int main()
{test();return 0;
}

输出结果

隔壁老王LaoWang类中的visit1()函数正在访问:客厅
隔壁老王LaoWang类中的visit1()函数正在访问:卧室
隔壁老王LaoWang类中的visit2()函数正在访问:客厅

参考连接黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难

C++:友元(看这一篇就够了)相关推荐

  1. C++ cin的使用,看这一篇就够了

    C++ cin的用法,看这一篇就够了 1 C++输入输出综述 C++ IO首先建立在为Unix环境开发的原始库函数上:ANSI C正式承认这个库时,将其称为标准输入/输出包: IO相关类定义在头文件i ...

  2. api网关选型_如何轻松打造百亿流量API网关?看这一篇就够了(下)

    如何轻松打造百亿流量API网关?看这一篇就够了(上) 上篇整体描述了网关的背景,涉及职能.分类.定位环节,本篇进入本文的重点,将会具体谈下百亿级流量API网关的演进过程. 准备好瓜子花生小板凳开始积累 ...

  3. python装饰器功能是冒泡排序怎么做_传说中Python最难理解的点|看这完篇就够了(装饰器)...

    https://mp.weixin.qq.com/s/B6pEZLrayqzJfMtLqiAfpQ 1.什么是装饰器 网上有人是这么评价装饰器的,我觉得写的很有趣,比喻的很形象 每个人都有的内裤主要是 ...

  4. serviceloader java_【java编程】ServiceLoader使用看这一篇就够了

    转载:https://www.jianshu.com/p/7601ba434ff4 想必大家多多少少听过spi,具体的解释我就不多说了.但是它具体是怎么实现的呢?它的原理是什么呢?下面我就围绕这两个问 ...

  5. docker 删除所有镜像_关于 Docker 镜像的操作,看完这篇就够啦 !(下)| 文末福利...

    紧接着上篇<关于 Docker 镜像的操作,看完这篇就够啦 !(上)>,奉上下篇 !!! 镜像作为 Docker 三大核心概念中最重要的一个关键词,它有很多操作,是您想学习容器技术不得不掌 ...

  6. mysql ip比较大小_MySQL优化/面试,看这一篇就够了

    原文链接:http://www.zhenganwen.top/articles/2018/12/25/1565048860202.html 作者:Anwen~ 链接:https://www.nowco ...

  7. 基础 | 零散的MySql基础记不住,看这一篇就够啦

    ❝ 这是小小本周的第二篇,本篇将会着重的讲解关于MySql基础的内容,MySql基础看这一篇就够啦. ❞ 送书反馈与继续送书 之情小微信公众号第一次送书,Java深度调试技术,书已经被中奖者麦洛签收, ...

  8. 【系统架构设计师】软考高级职称,一次通过,倾尽所有,看完这篇就够了,论软件架构设计的重要性、本篇论文“未通过考试”,供分析参考

    [系统架构设计师]软考高级职称,一次通过,倾尽所有,看完这篇就够了,学习方法和技巧这里全都有. 论软件架构设计的重要性.本篇论文未通过考试(不合格),供分析参考. 目录 摘要 正文 结尾 摘要 201 ...

  9. 深度好文:云网络丢包故障定位,看这一篇就够了~

    深度好文:云网络丢包故障定位,看这一篇就够了~ https://mp.weixin.qq.com/s/-Q1AkxUr9xzGKwUMV-FQhQ Alex 高效运维 今天 来源:本文经授权转自公众号 ...

  10. 代理后台中间件_Golang Gin 实战(十三)| 中间件详解看这一篇就够了

    6000字大章带你死磕Golang Gin中间件 在Gin的整个实现中,中间件可谓是Gin的精髓.一个个中间件组成一条中间件链,对HTTP Request请求进行拦截处理,实现了代码的解耦和分离,并且 ...

最新文章

  1. 理解Maven中的SNAPSHOT版本和正式版本
  2. SAP企业解决方案SAP Business One敏捷系列—敏捷制造
  3. ASP.NET的软件开发规范_转载
  4. AlwaysOn 2016 新特性和提升
  5. linux怎么检测文件完整性,Linux如何基于AIDE检测文件系统完整性
  6. 循环队列的进队算法c语言,循环队列的定义,入队算法,出队算法,遍历算法,及其代码实现-Go语言中文社区...
  7. UDP/TCP网络传输方式
  8. 不下载APP就不能看全文?工信部出手了...
  9. SpringMVC-数据处理(三)
  10. c#位图转换未矢量图_PS基础:像素与分辨率,位图与矢量图
  11. 【BX学习之软件著作权】 软件著作权的申请
  12. 国内外著名黑客杂志 《转》
  13. 2019西湖论剑网络安全技能大赛(大学生组)部分WriteUp
  14. H3C防火墙基础配置1-登录配置、安全域配置
  15. Word编号设置和跳到尾页快捷键
  16. Android 监听短信数据库过滤获取短信内容上传至服务器
  17. windows安装mysql-community-8.0.13.0
  18. 计算机基础理论科学家,科学家新理论:人类生活于计算机模拟程序中
  19. Vue-Uni-App小程序实现身份证识别
  20. 人工智能会“偷走”潜艇的隐身能力吗?

热门文章

  1. 刚和马云做了比较:马云学历比我高,我比马云帅!马云比我有钱,我比马云年轻!唉!打个平手!不说了,包工头,我去搬砖了
  2. soap和wsdl的理解
  3. Java配置及软件下载
  4. 啊,嗯,唔,啊,啊,啊,
  5. 在ArcGIS中提取所需地方区域的shp
  6. 再谈Comparator
  7. 花王连续14年被评为“全球最具道德企业”
  8. 黑马程序员 浅谈封装的具体实现的几种例子
  9. Pytorch中的torch.cat()函数
  10. Re4:读论文 CGSum: Enhancing Scientific Papers Summarization with Citation Graph