[C++ 从入门到精通] 15.友元函数、友元类、友元成员函数

  • 📢博客主页:https://loewen.blog.csdn.net
  • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
  • 📢本文由 丶布布原创,首发于 CSDN,转载注明出处🙉
  • 📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨

文章预览:

      • 一. 前言
      • 二. 友元函数
      • 三. 友元类
      • 四. 友元成员函数


一. 前言

众所周知,C++控制对类对象私有成员的访问。通常,公有类方法(public)提供唯一的访问途径,但是有时候这种限制太严格,以至于不适合特定的编程问题。

在这种情况下,C++提供了另外一种形式的访问权限:友元,友元有3种:

  • 友元函数;
  • 友元类;
  • 友元成员函数;

优缺点

  • 优点:通过让函数成为类的友元(即:友元函数),可以赋予该函数与类的成员函数相同的访问权限,使其可以访问本类protected、private成员,在某些频繁访问成员变量的地方可以提高性能。

  • 缺点:友元破坏了面向对象的封装性。


二. 友元函数

1、通过friend将一个函数(友元函数是个函数)声明为某个类的友元函数,那么该函数就能访问这个类的所有成员(成员变量、成员函数),无论是public,private,protected

2、因为友元函数不属于类成员,所以其不受public/protected/private的限制,放在public/protected/private下声明都行。

代码展示

#include <iostream>
using namespace std;class A
{
private:int data;void display(){cout << "data = " << data << endl;}friend void change(int x, A& a); // 将函数change()声明为类A的友元函数
};void change(int x, A& a)
{a.data = x;a.display();
}int main()
{A a;change(10, a);return 0;
}

三. 友元类

1、可以在类A中把类B声明为类A的友元类,此时,在类B(类A的友元类)的成员函数中,可以访问类A的所有成员(成员变量、成员函数),无论是public,private,protected

2、由于友元类不属于类成员,所以友元类的声明不受public、protected、private的影响。

代码展示Tip:为什么需要类B的声明):

#include <iostream>
using namespace std;class B; // 类B的声明,类A用到了类B,而类B的定义有可能在类A的定义之后导致编译出错,所以最好先声明一下类B
class A
{
private:int data;void display(){cout << "data = " << data << endl;}friend class B; // 将类B声明为类A的友元类(用到了类B的名字,所以需要前面声明一下class B; )
};class B
{
public:void change(int x, A& a){a.data = x;  //在类B(类A的友元类)的成员函数中,可以访问类A的所有成员(成员变量、成员函数),无论是public,private,protecteda.display();}
};int main()
{A a;B b;b.change(50, a);return 0;
}

注意:每个类都负责控制自己的友元类和友元函数:

  • 友元关系不能被继承
  • 友元关系是单向的,比如类B是类A的友元类,但这并不代表类A是类B的友元类;
  • 友元关系没有传递性,比如类B是类A的友元类,类C是类B的友元类,但这并不代表类C是类A的友元类;

四. 友元成员函数

友元成员函数:即是本类的成员函数,又是其他类的友元函数。

代码展示

A.h(Tip:为什么使用#include "B.h"而不用class B;声明类B

#ifndef __A_H
#define __A_H#include <iostream>//class B;   //注:声明友元成员函数不能仅仅使用类B的声明了,因为在friend void B::change(int x, A& a)不仅仅用到了类B的名字,//还用到了其成员函数change(),系统需要先判断类B中是否有其成员函数change(),所以需要用#include "B.h"
#include "B.h"class A
{
private:int data;void display(){std::cout << "data = " << data << std::endl;}friend void B::change(int x, A& a); // 该函数是友元成员函数的声明:将类B的成员函数change()声明为类A的友元函数
};#endif

B.h

#ifndef __B_H
#define __B_Hclass A; // 类A的声明class B
{
public:void change(int x, A& a); // 只有public的成员函数才能成为其它类的友元函数
};#endif

B.cpp

#include "A.h"
#include "B.h"void B::change(int x, A& a)
{a.data = x;a.display();
}

main.cpp

#include "A.h"
#include "B.h"int main()
{A a;B b;b.change(50, a);return 0;
}

下雨天,最惬意的事莫过于躺在床上静静听雨,雨中入眠,连梦里也长出青苔。

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

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

相关文章

统计分析绘图软件 GraphPad Prism 10 mac功能介绍

GraphPad Prism mac是一款专业的统计和绘图软件&#xff0c;主要用于生物医学研究、实验设计和数据分析。 GraphPad Prism mac功能和特点 数据导入和整理&#xff1a;GraphPad Prism 可以导入各种数据格式&#xff0c;并提供直观的界面用于整理、编辑和管理数据。用户可以轻松地…

qsort函数应用

1.引入 我们前面学习了一些常见的排序方法&#xff0c;比如冒泡排序等&#xff0c;但它仅局限于整型的排序&#xff0c;今天我们要介绍一个牛气哄哄的库函数qsort函数&#xff0c;这个函数可就厉害了&#xff0c;能排序任意类型数据&#xff0c;掌握后可谓受益终身&#xff0c;…

PyQt中的冒号(:)

在这段代码中&#xff0c;冒号&#xff08;:&#xff09;的使用是类型注解的一种形式&#xff0c;用于显式地指定变量的类型。在Python 3.5及以后的版本中&#xff0c;引入了类型注解的概念&#xff0c;可以在变量名后面使用冒号来注解变量的类型。 例如&#xff0c;在以下代码…

Python 安装第三方模块

要安装三方模块&#xff0c;需要知道模块的名字和pip。 pip来源&#xff1a; Mac、Linux无需安装自带。 Window:勾选了pip和add python.exe to Path 目录 安装Pillow 查看pip版本 命令行安装 查看本地安装库 升级pip 使用Pillow 引入三方库 打开图片 查看图片的信息 …

Metashape 自定义比例尺 / 无POS时如何制作DEM

前言操作步骤 前言 Metashape 自定义比例尺 和 无POS时如何制作DEM&#xff0c;此二者的操作步骤本质上是一样的。 当我们输入的照片没有POS&#xff0c;且没有做像控点的时候&#xff0c;比如我们仅仅拍摄了一个比较小的物体&#xff0c;可能是一瓶饮料或者一个椅子。 那么此…

C++刷题 -- KMP算法

C刷题 – KMP算法 文章目录 C刷题 -- KMP算法1.算法讲解2.算法实现 https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/description/ 1.算法讲解 KMP算法是一种字符串匹配算法&#xff0c;当出现字符串不匹配时&#xff0c;可以记录一部分之…

【>D:\10\Debug\RCa00828(34): fatal error RC1022: expected ‘#endif‘】

1>D:\10\Debug\RCa00828(34): fatal error RC1022: expected ‘#endif’ The error message you’re seeing, fatal error RC1022: expected ‘#endif’, indicates that the resource compiler encountered an issue when processing a resource script file (typically w…

【CLion】使用CLion开发STM32

本文主要记录使用CLion开发STM32&#xff0c;并调试相关功能 使用的CLion版本&#xff1a;2023.3.1 CLion嵌入式配置教程&#xff1a;STM32CubeMX项目 |CLion 文档 (jetbrains.com) OpenOCD官网下载&#xff1a;Download OpenOCD for Windows (gnutoolchains.com) GNU ARM工…

大话前端:WebAssembly的未来与前端开发

大话前端&#xff1a;WebAssembly的未来与前端开发 引言 近年来&#xff0c;WebAssembly&#xff08;简称Wasm&#xff09;作为一种新兴的网络技术&#xff0c;正在逐步改变前端开发的格局。作为一种低级的类汇编语言&#xff0c;它允许代码以接近原生的速度运行&#xff0c;…

lv12 linux 内核移植 10

目录 1 内核概述 1.1 内核与操作系统 1.2 Linux层次结构 1.3 Linux内核特点 2 Linux内核源码结构 2.1 Linux内核源码获取 2.2 源码结构 3 Linux内核移植 3.1 在 Linux 官网下载 Linux 内核源码&#xff08;这里我们下载 linux-3.14.tar.xz&#xff09; 3.2 拷贝内核源…

React中对UI组件化的步骤和设计原理

在 React 中&#xff0c;对 UI 进行组件化是一个将复杂界面拆分成更小、独立和可复用部分的过程。这种方法有助于提高应用的可维护性、可测试性&#xff0c;并且可以提升开发效率。下面是 React 中对 UI 组件化的步骤和设计原理的详细解释&#xff1a; 步骤一&#xff1a;识别…

uniapp组件和周期的知识点以及怎么使用

UniApp是一个使用Vue.js开发跨平台应用的框架&#xff0c;它可以将代码编译成微信小程序、支付宝小程序、H5、App等多个平台的应用。在UniApp中&#xff0c;组件是构建应用界面的基本单位&#xff0c;而生命周期则是组件在实例化、挂载、更新和销毁过程中的一系列方法。 以下是…

【Spark-ML源码解析】Word2Vec

前言 在阅读源码之前&#xff0c;需要了解Spark机器学习Pipline的概念。 相关阅读&#xff1a;SparkMLlib之Pipeline介绍及其应用 这里比较核心的两个概念是&#xff1a;Transformer和Estimator。 Transformer包括特征转换和学习后的模型两种情况&#xff0c;用来将一个DataFr…

Unity触摸 射线穿透UI解决

unity API 之EventSystem.current.IsPointerOverGameObject() 命名空间 &#xff1a;UnityEngine.EventSystems 官方描述&#xff1a; public bool IsPointerOverGameObject(); public bool IsPointerOverGameObject(int pointerId); //触摸屏时需要的参数&#xff…

支持向量机 支持向量机概述

支持向量机概述 支持向量机 Support Vector MachineSVM ) 是一类按监督学习 ( supervisedlearning)方式对数据进行二元分类的广义线性分类器 (generalized linear classifier) &#xff0c;其决策边界是对学习样本求解的最大边距超亚面 (maximum-margin hyperplane)与逻辑回归和…

Unity | Shader基础知识(第七集:案例<让图片和外部颜色叠加显示>)

目录 一、本节介绍 1 上集回顾 2 本节介绍 二、添加图片资源 三、 常用cg数据类型 1 float 2 bool 3 sampler 四、加入图片资源 五、使用图片资源 1 在通道里加入资源 2 使用图片和颜色叠加 2.1 2D纹理采样tex2D 2.2 组合颜色 六、全部代码 七、下集介绍 相关…

26 redis 中 replication/cluster 集群中的主从复制

前言 我们这里首先来看 redis 这边实现比较复杂的 replication集群模式 我们这里主要关注的是 redis 这边的主从同步的相关实现 这边相对比较简单, 我们直接基于 cluster集群模式 进行调试 主从命令同步复制 比如这里 master 是 redis_7002, slave 是 redis_7005 然后 这…

11.HarmonyOS鸿蒙app_page的显示跳转方法

11.HarmonyOS鸿蒙app_page的显示跳转方法&#xff0c;text文本触发点击事件 使用Intent和Operation对象 创建新项目后&#xff0c;再创建secondPageAbility ability_main.xml <?xml version"1.0" encoding"utf-8"?> <DirectionalLayoutxmlns:…

LeetCode(65)LRU 缓存【链表】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; LRU 缓存 1.题目 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 k…

【ArkTS】路由传参

传参 使用router.pushUrl()&#xff0c;router.push()官方不推荐再使用了。 格式&#xff1a; router.pushUrl({url: 路由地址,params:{参数名&#xff1a;值} )跳转时需要注意路由表中是否包含路由地址。 路由表路径&#xff1a; entry > src > main > resources &g…