当前位置: 首页 > news >正文

c++ 友元函数 友元类

1. 友元函数

1.1 简介

友元函数是在类的声明中声明的非成员函数,它被授予访问类的私有成员的权限。这意味着友元函数可以访问类的私有成员变量和私有成员函数,即使它们不是类的成员。
一个类中,可以将其他类或者函数声明为该类的友元,使得这些友元函数能够访问该类的私有成员和受保护成员。

1.2 特点

  1. 友元函数可以直接访问类的私有成员和受保护成员,包括私有成员变量和私有成员函数,无需通过对象或者类的接口来访问。
  2. 友元函数在声明时需要在类内部进行声明,并使用关键字 friend 进行修饰。但它不是类的成员函数,因此它在类的作用域之外定义和实现
  3. 友元关系是单向的:如果A是B的友元,那么B不一定是A的友元。
  4. 不继承权限,友元函数的权限仅限于声明它的类,而不会被派生类继承。

1.3 使用场景

  1. 访问私有成员
    当需要在某个外部函数中直接访问一个类的私有成员时,可以将该函数声明为友元函数。
#include <iostream>class MyClass {
private:int privateData;public:MyClass(int data) : privateData(data) {}friend void printPrivateData(const MyClass& obj);
};void printPrivateData(const MyClass& obj) {std::cout << "Private data: " << obj.privateData << std::endl;
}int main() {MyClass obj(42);printPrivateData(obj);  // 调用友元函数访问私有成员return 0;
}
  1. 实现操作符重载
#include <iostream>class Complex {
private:double real;double imaginary;public:Complex(double r, double i) : real(r), imaginary(i) {}friend std::ostream& operator<<(std::ostream& os, const Complex& obj);
};std::ostream& operator<<(std::ostream& os, const Complex& obj) {os << obj.real << " + " << obj.imaginary << "i";return os;
}int main() {Complex c(3.5, 2.5);std::cout << "Complex number: " << c << std::endl;  // 使用友元函数重载输出操作符return 0;
}

声明了一个友元函数operator<<,用于重载输出操作符<<,以便能够以自定义的方式打印Complex类的对象。在main函数中,我们创建了一个Complex对象c,并使用std::cout和友元函数operator<<来打印该对象的值。
3. 提供类之间的非成员函数接口
如果两个类之间需要共享信息或者互相调用对方的非公开成员,可以使用友元关系。

#include <iostream>class ClassB;class ClassA {
private:int data;public:ClassA(int d) : data(d) {}friend void processData(const ClassA& objA, const ClassB& objB);
};class ClassB {
private:int data;public:ClassB(int d) : data(d) {}friend void processData(const ClassA& objA, const ClassB& objB);
};void processData(const ClassA& objA, const ClassB& objB) {std::cout << "Data from ClassA: " << objA.data << std::endl;std::cout << "Data from ClassB: " << objB.data << std::endl;
}int main() {ClassA objA(42);ClassB objB(24);processData(objA, objB);  // 调用友元函数处理两个类的数据return 0;
}

定义了两个类ClassA和ClassB,并在它们之间声明了一个友元函数processData。这个函数可以访问ClassA和ClassB的私有成员变量,并在函数中处理这些数据。在main函数中,我们创建了一个ClassA对象objA和一个ClassB对象objB,然后调用友元函数processData来处理这两个类的数据。

1.4 注意

  1. 友元关系破坏了封装性原则,因此应谨慎使用。过度依赖友元关系可能会导致代码不易维护和扩展。
  2. 友元关系没有继承性质,只限于被声明为友元的类或者函数能够访问相应的成员。

2. 友元类

2.1 简介

C++中的友元类(friend class)是指一个类可以将另一个类声明为友元,从而允许友元类访问其私有成员。

2.2 特点

  1. 友元关系是单向的:如果类A是类B的友元,则只有类B能够访问类A的私有和保护成员,反之则不成立。
  2. 友元关系不可传递:即使类A是类B的友元,而类B又是类C的友元,但并不能推导出类A是类C的友元。
  3. 友元关系没有继承性:即使派生类继承了基类,基类中声明为友元的其他类并不会自动成为派生类的友元。

2.3 使用场景

  1. 信息封装:当一个类需要将其私有成员暴露给另一个类以实现特定功能时,可以将另一个类声明为友元类。这样,友元类就可以直接访问声明它的类的私有成员,从而实现类之间的信息封装。
  2. 成员访问优化:有时候,多个类之间需要频繁访问彼此的私有成员,而不希望通过公有接口进行访问。在这种情况下,可以将这些类声明为友元类,以提高成员访问的效率。

代码:

class FriendClass {
private:int privateData;public:FriendClass(int data) : privateData(data) {}friend class MyClass;
};class MyClass {
public:void accessFriendData(const FriendClass& obj) {int data = obj.privateData;  // 友元类可以访问FriendClass的私有成员}
};int main() {FriendClass obj(42);MyClass myObj;myObj.accessFriendData(obj);  // MyClass通过友元类访问FriendClass的私有成员return 0;
}

上述示例中,定义了两个类FriendClass和MyClass。FriendClass将MyClass声明为友元类,从而允许MyClass访问FriendClass的私有成员变量privateData。在MyClass中,我们定义了一个成员函数accessFriendData,它通过友元类的权限访问FriendClass的私有成员。在main函数中,创建了FriendClass的对象obj和MyClass的对象myObj,并通过myObj调用accessFriendData来访问FriendClass的私有成员。

两个代码互为友元,代码:

#include <iostream>using namespace std;class B; // 前向声明class A {
private:int privateDataA;
public:A() : privateDataA() {};friend class B; // 声明B为A的友元类void displayPrivateData(const B& b);
};class B {
private:int privateDataB;
public:B() : privateDataB(10) {};friend class A; // 声明A为B的友元类void setPrivateData( A & a, int data) {a.privateDataA = data; // 可以直接访问A中的私有成员cout << "Successfully set private data of A from B: " << a.privateDataA << endl;}
};void A::displayPrivateData(const B & b) {cout << "Accessing private data of B from A: " << b.privateDataB << endl;
}int main() {A a;B b;b.setPrivateData(a, 42); // 通过B类的成员函数修改A类的私有成员数据a.displayPrivateData(b); // 通过A类的成员函数访问B类的私有成员数据return 0;
}

运行结果:

Successfully set private data of A from B: 42
Accessing private data of B from A: 10

A和B是两个类。通过将彼此声明为友元类,它们可以直接访问对方的私有成员。在主函数中,我们创建了一个A对象a和一个B对象b,并使用友元函数setPrivateData从b中修改了a的私有成员数据,并使用友元函数displayPrivateData从a中访问了b的私有成员数据。

相关文章:

c++ 友元函数 友元类

1. 友元函数 1.1 简介 友元函数是在类的声明中声明的非成员函数&#xff0c;它被授予访问类的私有成员的权限。这意味着友元函数可以访问类的私有成员变量和私有成员函数&#xff0c;即使它们不是类的成员。 一个类中&#xff0c;可以将其他类或者函数声明为该类的友元&#…...

Spring推断构造器源码分析

Spring中bean虽然可以通过多种方式&#xff08;Supplier接口、FactoryMethod、构造器&#xff09;创建bean的实例对象&#xff0c;但是使用最多的还是通过构造器创建对象实例&#xff0c;也是我们最熟悉的创建对象的方式。如果有多个构造器时&#xff0c;那Spring是如何推断使用…...

十五、【历史记录画笔工具组】

文章目录 历史记录画笔工具历史记录艺术画笔工具 历史记录画笔工具 历史记录画笔工具很简单&#xff0c;就是将画笔工具嗯&#xff0c;涂抹过的修改过的地方&#xff0c;然后用历史记录画笔工具重新修改回来&#xff0c;比如我们将三叠美元中的一叠用画笔工具先涂抹掉&#xf…...

Spark上使用pandas API快速入门

文章最前&#xff1a; 我是Octopus&#xff0c;这个名字来源于我的中文名--章鱼&#xff1b;我热爱编程、热爱算法、热爱开源。所有源码在我的个人github &#xff1b;这博客是记录我学习的点点滴滴&#xff0c;如果您对 Python、Java、AI、算法有兴趣&#xff0c;可以关注我的…...

【WebRTC---源码篇】(十:零)WEBRTC/StreamStatisticianImpl持续更新中)

StreamStatisticianImpl是WebRTC的一个内部实现类&#xff0c;用于统计和管理媒体流的各种统计信息。 StreamStatisticianImpl负责记录和计算以下统计数据&#xff1a; 1. 带宽统计&#xff1a;记录媒体流的发送和接收带宽信息&#xff0c;包括发送比特率、接收比特率、发送丢…...

​调用Lua脚本tostring(xxx)报attempt to call a nil value (global ‘tostring‘

在c程序里调用Lua脚本, 脚本中用到了转字符串 tostring(xxx) str "test" function output(a,b,c)d "a:"..tostring(a).."b:"..tostring(b).."c"..tostring(c)return d end 实际运行会报错&#xff1a; attempt to call a nil v…...

PBA.客户需求分析 需求管理

一、客户需求分析 1 需求的三个层次: Requirement/Wants/Pains 大部分人认为&#xff0c;产品满足不了客户需要&#xff0c;是因为客户告知的需求是错误的&#xff0c;这听起来有一些道理&#xff0c;却没有任何意义。不同角色对于需求的理解是不一样的。在客户的需求和厂家的…...

Kafka进阶

Kafka进阶 Kafka事务 kafka的事务机制是指kafka支持跨多个主题和分区的原子性写入&#xff0c;即在一个事务中发送的所有消息要么全部成功&#xff0c;要么全部失败。 kafka的事务机制涉及到以下几个方面&#xff1a; 事务生产者&#xff08;transactional producer&#x…...

大数计算:e^1000/300!

1.问题&#xff1a;大数计算可能超出数据类型范围 当单独计算 &#xff0c;因为 &#xff0c;double的最大取值为1.79769e308&#xff0c;所以 肯定超过了double的表示范围。 同样&#xff0c;对于300&#xff01;也是如此。 那我们应该怎么去计算和存储结果呢&#xff1f;…...

力扣164最大间距

1.前言 因为昨天写了一个基数排序&#xff0c;今天我来写一道用基数排序实现的题解&#xff0c;希望可以帮助你理解基数排序。 这个题本身不难&#xff0c;就是线性时间和线性额外空间(O(n))的算法&#xff0c;有点难实现 基数排序的时间复杂度是O(d*(nradix))&#xff0c;其中…...

聚观早报 | “百度世界2023”即将举办;2024款岚图梦想家上市

【聚观365】10月13日消息 “百度世界2023”即将举办 2024款岚图梦想家上市 腾势D9用户超10万 华为发布新一代GigaGreen Radio OpenAI拟进行重大更新 “百度世界2023”即将举办 “百度世界2023”将于10月17日在北京首钢园举办。届时&#xff0c;百度创始人、董事长兼首席执…...

Windows 应用程序监控重启

执行思路 1.定时关闭可执行程序&#xff0c;2.再通过定时监控启动可执行程序 定时启动关闭程序.bat echo off cd "D:\xxxx\" :: 可执行程序目录 Start "" /b xxxx.exe :: 可执行程序 timeout /T 600 /nobreak >nul :: 600秒 taskkill /IM xxxx.exe /…...

springboot 通过url下载文件并上传到OSS

DEMO流程 传入一个需要下载并上传的url地址下载文件上传文件并返回OSS的url地址 springboot pom文件依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w…...

docker创建elasticsearch、elasticsearch-head部署及简单操作

elasticsearch部署 1 拉取elasticsearch镜像 docker pull elasticsearch:7.7.0 2 创建文件映射路径 mkdir /mydata/elasticsearch/data mkdir /mydata/elasticsearch/plugins mkdir /mydata/elasticsearch/config 3 文件夹授权 chmod 777 /mydata/elastic…...

竞赛选题 深度学习+python+opencv实现动物识别 - 图像识别

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 inception_v3网络5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; *…...

Codeforces Round 903 (Div. 3)ABCDE

Codeforces Round 903 (Div. 3)ABCDE 目录 A. Dont Try to Count题目大意思路核心代码 B. Three Threadlets题目大意思路核心代码 C. Perfect Square题目大意思路核心代码 D. Divide and Equalize题目大意思路核心代码 E. Block Sequence题目大意思路核心代码 A. Don’t Try t…...

C# 与 C/C++ 的交互

什么是平台调用 (P/Invoke) P/Invoke 是可用于从托管代码访问非托管库中的结构、回调和函数的一种技术。 托管代码与非托管的区别 托管代码和非托管代码的主要区别是内存管理方式和对计算机资源的访问方式。托管代码通常运行在托管环境中&#xff0c;如 mono 或 java 虚拟机等…...

新版Android Studio搜索不到Lombok以及无法安装Lombok插件的问题

前言 在最近新版本的Android Studio中&#xff0c;使用插件时&#xff0c;在插件市场无法找到Lombox Plugin&#xff0c;具体表现如下图所示&#xff1a; 1、操作步骤&#xff1a; &#xff08;1&#xff09;打开Android Studio->Settings->Plugins&#xff0c;搜索Lom…...

BST二叉搜索树

文章目录 概述实现创建节点查找节点增加节点查找后驱值根据关键词删除找到树中所有小于key的节点的value 概述 二叉搜索树&#xff0c;它具有以下的特性&#xff0c;树节点具有一个key属性&#xff0c;不同节点之间key是不能重复的&#xff0c;对于任意一个节点&#xff0c;它…...

【Leetcode】211. 添加与搜索单词 - 数据结构设计

一、题目 1、题目描述 请你设计一个数据结构&#xff0c;支持 添加新单词 和 查找字符串是否与任何先前添加的字符串匹配 。 实现词典类 WordDictionary &#xff1a; WordDictionary() 初始化词典对象void addWord(word) 将 word 添加到数据结构中&#xff0c;之后可以对它…...

Discuz户外旅游|旅行游记模板/Discuz!旅行社、旅游行业门户网站模板

价值328的discuz户外旅游|旅行游记模板&#xff0c;本模板需要配套【仁天际-PC模板管理】插件使用。 模板说明 1、模板页面宽度1200px&#xff0c;简洁大气&#xff0c;较适合户外旅行、骑行、游记、摩旅、旅游、活动等类型的论坛、频道网站&#xff1b; 2、所优化的页面有&…...

【重拾C语言】十一、外部数据组织——文件

目录 前言 十一、外部数据组织——文件 11.1 重新考虑户籍管理问题——文件 11.2 文件概述 11.2.1 文件分类 11.2.2 文件指针、标记及文件操作 11.3 打开、关闭文件 11.4 I/O操作 11.4.1 字符读写 11.4.2 字符串读写 11.4.3 格式化读写 11.4.4 数据块读写 11.4.5 …...

dpdk/spdk/网络协议栈/存储/网关开发/网络安全/虚拟化/ 0vS/TRex/dpvs技术专家成长体系教程

课程围绕安全&#xff0c;网络&#xff0c;存储&#xff0c;云原生4个维度去讲解核心技术点。 6个专栏组成&#xff1a;dpdk网络专栏、存储技术专栏、安全与网关开发专栏、虚拟化与云原生专栏、测试工具专栏、性能测试专栏 一、dpdk网络 dpdk基础知识 多队列网卡&#xff0…...

树莓派玩转openwrt软路由:5.OpenWrt防火墙配置及SSH连接

1、SSH配置 打开System -> Administration&#xff0c;打开SSH Access将Interface配置成unspecified。 如果选中其他的接口表示仅在给定接口上侦听&#xff0c;如果未指定&#xff0c;则在所有接口上侦听。在未指定下&#xff0c;所有的接口均可通过SSH访问认证。 2、防火…...

Gin:获取本机IP,获取访问IP

获取本机IP func GetLocalIP() []string {var ipStr []stringnetInterfaces, err : net.Interfaces()if err ! nil {fmt.Println("net.Interfaces error:", err.Error())return ipStr}for i : 0; i < len(netInterfaces); i {if (netInterfaces[i].Flags & ne…...

缓存降级代码结构设计

缓存降级设计思想 接前文缺陷点 本地探针应该增加计数器&#xff0c;多次异常再设置&#xff0c;避免网络波动造成误判。耦合度过高&#xff0c;远端缓存和本地缓存应该平行关系被设计为上下游关系了。公用的远端缓存的操作方法应该私有化&#xff0c;避免集成方代码误操作&…...

一文深入理解高并发服务器性能优化

我们现在已经搞定了 C10K并发连接问题 &#xff0c;升级一下&#xff0c;如何支持千万级的并发连接&#xff1f;你可能说&#xff0c;这不可能。你说错了&#xff0c;现在的系统可以支持千万级的并发连接&#xff0c;只不过所使用的那些激进的技术&#xff0c;并不为人所熟悉。…...

pytorch中的归一化函数

在 PyTorch 的 nn 模块中&#xff0c;有一些常见的归一化函数&#xff0c;用于在深度学习模型中进行数据的标准化和归一化。以下是一些常见的归一化函数&#xff1a; nn.BatchNorm1d, nn.BatchNorm2d, nn.BatchNorm3d&#xff1a; 这些函数用于批量归一化 (Batch Normalization…...

【管理运筹学】第 10 章 | 排队论(1,排队论的基本概念)

文章目录 引言一、基本概念1.1 排队过程1.2 排队系统的组成和特征1.3 排队模型的分类1.4 系统指标1.5 系统状态 引言 开一点排队论的内容吧&#xff0c;方便做题。 排队论&#xff08;Queuing Theory&#xff09;也称随机服务系统理论&#xff0c;是为解决一系列排队问题&…...

【Express】服务端渲染(模板引擎 EJS)

EJS&#xff08;Embedded JavaScript&#xff09;是一款流行的模板引擎&#xff0c;可以用于在Express中创建动态的HTML页面。它允许在HTML模板中嵌入JavaScript代码&#xff0c;并且能够生成基于数据的动态内容。 下面是一个详细的讲解和示例&#xff0c;演示如何在Express中…...