C++ 友元函数和友元类

前言

        在本文中,您将学习在C ++中创建友元函数和友元类,并在程序中有效地使用它们。OOP的重要概念之一是数据隐藏,即非成员函数无法访问对象的私有或受保护的数据。但是,有时这种限制可能迫使程序员编写冗长而复杂的代码。因此,C ++编程内置了一种机制,可以从非成员函数访问私有或受保护的数据,这是使用友元函数和友元类完成的。

C ++中的友元函数

        如果将函数定义为友元函数,则可以使用函数访问类的私有数据和受保护数据。通过使用关键字friend,编译器知道给定的函数是友元函数。要访问数据,应该在类的内部以关键字friend开始声明友元函数(可以是类内部的任何地方,可以是private部分,也可以是public部分)。

C ++中的友元函数声明

class class_name
{... .. ...friend return_type function_name(argument/s);... .. ...
}

现在,您可以将友元函数定义为访问该类数据的普通函数。friend定义中未使用任何关键字。

class className
{... .. ...friend return_type functionName(argument/s);... .. ...
}return_type functionName(argument/s)
{... .. ...// 可以从这个位置访问className的私有和受保护数据//因为此函数是className的友元函数。... .. ...
}

 

/* C ++程序演示友元函数的工作。*/
#include<iostream>
class base {
public:// 友元函数friend int display_friend(base);
private:int a = 1;
protected:int b = 2;
};// 友元函数的定义
int display_friend(base m) {//从非成员函数访问私有数据和受保护数据int c = m.a + m.b;return c;
}int main() {base base1;std::cout << "输出:" << display_friend(base1) << std::endl;system("pause");return 0;
}

输出结果:

3

分析:

        这里,友元函数display_friend() 在base类中声明。因此,可以从这个函数访问类中的私有数据和受保护数据。

若将友元函数在类中的声明去掉,则程序会报错:
去掉友元函数在类中的声明之后代码如下:

/* C ++程序演示友元函数的工作。*/
#include<iostream>
class base {
public:// 友元函数//friend int display_friend(base);
private:int a = 1;
protected:int b = 2;
};// 友元函数的定义
int display_friend(base m) {//从非成员函数访问私有数据和受保护数据int c = m.a + m.b;return c;
}int main() {base base1;std::cout << "输出:" << display_friend(base1) << std::endl;system("pause");return 0;
}

编译器报错: 

使用友元函数添加两个不同类的私有或受保护成员变量

#include<iostream>
class base2; // 类base2的前置声明class base1 {
public:// 友元函数声明friend int display_friend(base1, base2);
private:int a = 1;
};class base2 {
public:// 友元函数声明friend int display_friend(base1, base2);protected:int b = 2;
};// 友元函数的定义
// 函数display_friend()是类base1和base2的友元函数
int display_friend(base1 m1, base2 m2) {//从非成员函数访问私有数据和受保护数据int c = m1.a + m2.b;return c;
}int main() {base1 A;base2 B;std::cout << "输出:" << display_friend(A, B) << std::endl;system("pause");return 0;
}

 输出结果:

3

分析:

        在这个程序中,类base1和base2已经将display_friend()声明为friend函数。因此,这个函数可以访问这两个类的私有数据或受保护数据。在这里,display_friend()函数将两个对象A和B的私有数据 a 和受保护数据 b 相加,并将其返回给main函数。

        为了使这个程序正常工作,应该像上面的实例中所示的那样,对一个类base2进行前置声明。这是因为使用以下代码在class base1中引用了class base2的友元函数:friend int display_friend(base1,base2);

友元类(friend class)

        类似地,像一个友元函数一样,一个类也可以使用关键字friend成为另一个类的友元类。例如:

... .. ...
class B;
class A
{// class B 是 class A的友元类friend class B;... .. ...
}class B
{... .. ...
}

        当一个类成为另一个类的friend类(友元类)时,这就意味着这个类的所有成员函数都是另一个类的友元函数。

        在这个程序中,B类的所有成员函数都是A类的朋友函数,因此B类的任何成员函数都可以访问A类的私有和受保护的数据,但是A类的成员函数不能访问B类的数据。

例如下面的代码:

#include<iostream>
class B; // 前置声明class A {// class B 是class A的友元类friend class B;private:int a = 1;
protected:int b = 2;
};class B {public:// 类B的成员函数int displayB(A a1) {int c = a1.a + a1.b;return c;}
};int main() {A a2;B b2;std::cout << b2.displayB(a2) << std::endl;
}

输出结果:

3

分析: 

        类B 为类A 的友元类,类B中的成员函数可以访问类A的私有数据和受保护数据。

C ++编程中如何互为友元类

        如何实现classA与B互为友元,即A可以访问B的私有,B也可以访问A的私有呢?案例如下:

#include<iostream>
class B; // 前置声明class A {// class B 是class A的友元类friend class B;private:int a = 1;
protected:int b = 2;
public:int displayA(B);
};class B {// class A 是class B 的友元类friend class A;public:// 类B的成员函数int displayB(A a1) {int c = a1.a + a1.b;return c;}
private:int e = 3;
protected:int f = 4;
};// 类A的成员函数
int A::displayA(B b1) {int g = b1.e + b1.f;return g;
}int main() {A a2;B b2;std::cout << b2.displayB(a2) << std::endl; // 3std::cout << a2.displayA(b2) << std::endl; // 7
}

输出结果:
3
7

互为友元类的做法就是,在class A中声明friend class B;在classB 中声明friend class A;

注意:类A中使用到了类B的地方必须在类B的声明后定义,在类A中只能声明。例如上边类A中的displayA() 函数,不能在类A中直接定义,只能放在类B的声明之后定义。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/113087.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 ClickHouse 深入了解 Apache Parquet (一)

​ 【squids.cn】 全网zui低价RDS&#xff0c;免费的迁移工具DBMotion、数据库备份工具DBTwin、SQL开发工具等 自2013年作为Hadoop的列存储发布以来&#xff0c;Parquet几乎已经成为一种无处不在的文件交换格式&#xff0c;它提供了高效的存储和检索。这种采纳使其成为更近期的…

【六:pytest框架介绍】

常见的请求对象requests.get()requests.post()requests.delete()requests.put()requests.request()常见的响应对象reprequests.request()//返回字符串格式数据print(req.text)//返回字节格式数据print(req.content)//返回字典格式数据print(req.json)#状态码print(req.status_c…

GC overhead limit exceeded问题

1.问题现象 程序包运行时候发生了java.lang.OutOfMemoryError: GC overhead limit exceeded异常&#xff0c; 详细信息如下 org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: org.jboss.util.NestedSQLException: Error; - nested t…

【斗罗二】冰帝两次险些杀死雨浩,天梦哥求助伊老遭拒绝,霍云儿现身救儿子

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析绝世唐门。 斗罗大陆动画第二部绝世唐门已经更新了&#xff0c;霍雨浩与冰帝完美融合&#xff0c;成功觉醒了第二武魂&#xff0c;霍挂的时代正式到来。只是在整个第19集中&#xff0c;官方做了大量的改编&#xff0c;不但…

AC修炼计划(AtCoder Regular Contest 167)

传送门&#xff1a;AtCoder Regular Contest 167 - AtCoder 再次感谢樱雪喵大佬的题解&#xff0c;讲的很详细&#xff0c;Orz。 大佬的博客链接如下&#xff1a;Atcoder Regular Contest 167 - 樱雪喵 - 博客园 (cnblogs.com) 第一题很签到&#xff0c;就省略掉了。 第二题…

数据结构——二叉树的公共祖先问题

数据结构——二叉树的公共祖先问题 236. 二叉树的最近公共祖先思路 235. 二叉搜索树的最近公共祖先思路1.递归2.迭代 236. 二叉树的最近公共祖先 236. 二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#x…

(矩阵) 289. 生命游戏 ——【Leetcode每日一题】

❓ 289. 生命游戏 难度&#xff1a;中等 根据 百度百科 &#xff0c; 生命游戏 &#xff0c;简称为 生命 &#xff0c;是英国数学家约翰何顿康威在 1970 年发明的细胞自动机。 给定一个包含 m n 个格子的面板&#xff0c;每一个格子都可以看成是一个细胞。每个细胞都具有一…

16-spring AOP核心对象的创建

文章目录 1. aop的几个重要概念2. aop bean definition3. AspectJPointcutAdvisor4.AopConfigUtils5.AnnotationAwareAspectJAutoProxyCreator6. 循环依赖 1. aop的几个重要概念 参考官方解释&#xff1a;https://docs.spring.io/spring-framework/docs/5.2.9.RELEASE/spring-…

大数据之LibrA数据库系统概览

实时监控 “实时监控”页面如图1所示&#xff0c;用户可单击刷新按钮手动刷新当前页面&#xff0c;也可在点刷新按钮前选择自动刷新时长&#xff0c;刷新时长包括&#xff1a;每30秒刷新一次、每60秒刷新一次、停止刷新。 实时监控数据&#xff08;监控时间轴产生的新曲线&am…

Oracle数据中如何在 where in() 条件传参

一、问题场景描述 在sql 条件中&#xff0c;如何在 where in()中想传入参数&#xff0c;如果直接 where in(:seqList)&#xff0c;当传入单个值&#xff0c;seqList: ‘80’ 是没问题的&#xff0c;但是初入多个值时&#xff0c;seqList: ‘80,90’ &#xff0c;因缺少单引号&…

2 用TensorFlow构建一个简单的神经网络

上一篇&#xff1a;1 如何入门TensorFlow-CSDN博客 环境搭建 后续介绍的相关代码都是在pycharm运行&#xff0c;pycharm安装略。 打开pycharm&#xff0c;创建一个新的项目用于tensorflow编码练习&#xff0c;在Terminal输入命令&#xff1a; # 依赖最新版本的pip pip inst…

Pytest自动化测试框架之Allure报告详解

简介 Allure Framework是一种灵活的、轻量级、多语言测试报告工具。 不仅可以以简洁的网络报告形式非常简洁地显示已测试的内容&#xff0c; 而且还允许参与开发过程的每个人从日常执行中提取最大程度的有用信息和测试。 从开发/测试的角度来看&#xff1a; Allure报告可以…

线性代数的本质笔记

课程来自b站发现的《线性代数的本质》&#xff0c;可以帮助从直觉层面理解线性代数的一些基础概念&#xff0c;以及把一些看似不同的数学概念解释之后&#xff0c;发现其实有内在的关联。 这里只对部分内容做一个记录&#xff0c;完整内容请自行观看视频~ 01-向量究竟是什么 …

LeetCode 2316. 统计无向图中无法互相到达点对数::广度优先搜索(BFS)

【LetMeFly】2316.统计无向图中无法互相到达点对数&#xff1a;广度优先搜索&#xff08;BFS&#xff09; 力扣题目链接&#xff1a;https://leetcode.cn/problems/count-unreachable-pairs-of-nodes-in-an-undirected-graph/ 给你一个整数 n &#xff0c;表示一张 无向图 中…

2023年中国酒类新零售行业发展概况分析:线上线下渠道趋向深度融合[图]

近年来&#xff0c;我国新零售业态不断发展&#xff0c;线上便捷性和个性化推荐的优势逐步在放大&#xff0c;线下渠道智慧化水平持续提升&#xff0c;线上线下渠道趋向深度融合。2022年&#xff0c;我国酒类新零售市场规模约为1516亿元&#xff0c;预计2025年酒类新零售市场规…

Mysql——查询sql语句练习

一、单表查询 素材&#xff1a; 表名&#xff1a;worker-- 表中字段均为中文&#xff0c;比如 部门号 工资 职工号 参加工作 等 1、显示所有职工的基本信息。 select * from worker; 2、查询所有职工所属部门的部门号&#xff0c;不显示重复的部门号。 select distinct 部门号…

使用Chrome浏览器进行网页截图

在需要截图的网页上&#xff0c;按F12打开开发调试页面&#xff0c;再按下ShiftCtrlP&#xff0c;打开命令输入框&#xff0c;输入Capture&#xff0c; 此时会弹出4中截图模式&#xff0c;我个人比较喜欢用Capture full size screenshot Capture area screenshot&#xff0c;…

2023年中国纸箱机械优点、市场规模及发展前景分析[图]

纸箱机械行业是指涉及纸箱生产和加工的机械设备制造、销售和相关服务的产业。这个行业的主要任务是设计、制造和提供用于生产各种类型和规格纸箱的机械设备&#xff0c;以满足包装行业对纸箱的不同需求。 纸箱机械行业优点 资料来源&#xff1a;共研产业咨询&#xff08;共研网…

将语义分割的标注mask转为目标检测的bbox

1. 语义分割标签 1.1 labelme工具 语义分割的标签是利用labelme工具进行标注的,标注的样式如下: 1.2 语义分割的标签样式 2. 转换语义分割的标注到目标检测的bbox 实现步骤 (1) 利用标注的json文件生成mask图片(2) 在mask图片中找到目标的bbox矩形框的左上角点和右下角点(…

d3dx9_43.dll丢失怎么解决,四个解决方法帮你解决d3dx9_43.dll丢失

随着科技的不断发展&#xff0c;我们越来越依赖各种软件和硬件设备来提高生活和工作效率。然而&#xff0c;有时候我们可能会遇到一些技术问题&#xff0c;如“d3dx9_43.dll丢失”的问题。这个问题可能导致某些程序无法正常运行&#xff0c;给我们的生活带来诸多不便。因此&…