C++ 中的友元(Friend)用法详解

news2024/10/23 17:50:09

什么是友元(Friend)?👭

友元 (C++) | Microsoft Learn

在C++中,友元(Friend)是一种机制,允许外部函数或类访问某个类的私有(private)或保护(protected)成员

⚠️⚠️友元不是类的成员,但它能绕过封装限制,直接访问类中的私有数据。

2. 友元函数的定义与作用🆙
 

普通成员函数的访问限制

假设有一个类 Person,如下所示:

class Person {
private:
    std::string name;
    int age;
public:
    Person(std::string n, int a) : name(n), age(a) {}
};

在上面的例子中,name age 是私有成员,一般情况下不能从类外直接访问。

 友元函数如何访问私有数据

我们可以定义一个友元函数,允许它直接访问 Person 类的私有成员:

#include <iostream>
using namespace std;
class Person {
private:
    std::string name;
    int age;
public:
    Person(std::string n, int a) : name(n), age(a) {}

    // 声明友元函数
    friend void displayPersonInfo(const Person& p);
};

// 友元函数的实现
void displayPersonInfo(const Person& p) {
    std::cout << "Name: " << p.name << ", Age: " << p.age << std::endl;
}

int main() {
    Person p1("Alice", 30);
    displayPersonInfo(p1); 
    return 0;
}

解释:

  • friend 关键字用于声明 displayPersonInfoPerson 类的友元函数。

  • 虽然 displayPersonInfo 不是 Person 类的成员,但它能访问 nameage

3. 友元类的概念与使用😮‍💨

除了友元函数,C++ 还允许一个类成为另一个类的友元,从而使该类的所有成员函数都能访问另一个类的私有成员。

友元类的示例:

#include <iostream>
using namespace std;
class Engine {
private:
    int horsepower;
public:
    Engine(int hp) : horsepower(hp) {}

    // 声明 Car 为友元类
    friend class Car;
};

class Car {
public:
    void showEnginePower(const Engine& e) {
        std::cout << "Engine horsepower: " << e.horsepower << std::endl;
    }
};

int main() {
    Engine engine(500);
    Car car;
    car.showEnginePower(engine);  
    return 0;
}

解释:

这里,CarEngine 的友元类,因此 Car 的成员函数可以访问 Engine 的私有数据 horsepower

4. 友元的实际案例:为什么以及何时使用?

典型使用场景:

  1. 重载运算符: 需要通过友元函数访问类的私有成员来实现运算符重载

  2. 辅助调试或测试: 有时为了更方便地测试类中的私有数据,可以使用友元。

  3. 跨类协作: 当两个类高度耦合时,可以通过友元类减少重复代码

例子:运算符重载

class Complex {
private:
    double real, imag;
public:
    Complex(double r, double i) : real(r), imag(i) {}

    // 声明友元函数重载 '+' 运算符
    friend Complex operator+(const Complex& c1, const Complex& c2);
};

// 重载 '+' 运算符
Complex operator+(const Complex& c1, const Complex& c2) {
    return Complex(c1.real + c2.real, c1.imag + c2.imag);
}

int main() {
    Complex c1(1.0, 2.0), c2(3.0, 4.0);
    Complex c3 = c1 + c2;
    std::cout << "Real: " << c3.real << ", Imag: " << c3.imag << std::endl;
    return 0;
}

解释:

  • operator+ 是一个友元函数,用于访问 Complex 类的私有成员 realimag

5. 注意事项⚠️

  1. 破坏封装性: 使用友元会暴露类的私有数据,容易破坏封装性,因此要慎用。

  2. 维护复杂性: 如果过多使用友元类或友元函数,类之间的耦合度会增加,导致代码难以维护。

6. 图解:类与友元的关系

图示:友元函数访问类的私有成员

说明:

图中展示了 Person displayPersonInfo 友元函数的关系。即使 nameage 是私有的,displayPersonInfo 仍然能访问它们。

 复盘吧💪

  • 友元函数友元类允许类的私有成员对外开放,但应谨慎使用。

  • 友元机制非常适用于重载运算符或跨类访问数据的情况,但滥用可能导致代码的耦合性和维护成本增加。

对类访问不是很理解的可以看这篇

C++类域访问方式(public,protected,private)对象访问 , 通过成员函数访问 ,通过友元函数访问-CSDN博客文章浏览阅读144次。C++类的域访问方式主要由访问修饰符控制。了解这些访问方式可以帮助我们设计更安全和可维护的类。通过合理的封装,可以有效保护数据的完整性。https://blog.csdn.net/LJY_CF/article/details/143084393?spm=1001.2014.3001.5502

共勉 💪

同为未来的it人让我们在共同进步吧。

我很喜欢雷军的一段话:我们就悄悄的干,就算失败了咱也不丢人。

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

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

相关文章

[Unity Demo]从零开始制作空洞骑士Hollow Knight第十五集:制作更多地图,更多敌人,更多可交互对象

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、第一个代表性场景 1.制作更多敌人2.制作更多可交互对象二、第二个代表性场景 1.制作更多敌人2.制作更多可交互对象三、第三个代表性场景 1.制作更多敌人2.制…

【计算机网络 - 基础问题】每日 3 题(五十二)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞…

Solr5.5.0单机部署

Solr5.5.0集成Tomcat8部署 1、 准备条件 JDK1.7以上 Solr5.5.0部署包&#xff08;solr-5.5.0.zip&#xff09; Tomcat8部署包 &#xff08;apache-tomcat-8.5.16.tar.gz&#xff09; 上传Solr5.5.0和tomcat8 部署包并解压使用 2、准备部署 将./solr-5.5.0/server/solr-we…

SPI的学习

工作原理 SPI的工作原理基于主从架构。主设备通过四条主要信号线与一个或多个从设备进行通信&#xff1a; MOSI&#xff08;主输出&#xff0c;从输入&#xff09;DI&#xff08;Master Output Slave Input&#xff09;&#xff1a;主设备发送数据到从设备。MISO&#xff08;…

MySQL 回收表碎片实践教程

前言&#xff1a; 在 MySQL 数据库中&#xff0c;随着数据的增删改操作&#xff0c;表空间可能会出现碎片化&#xff0c;这不仅会占用额外的存储空间&#xff0c;还可能降低表的扫描效率&#xff0c;特别是一些大表&#xff0c;在进行数据清理后会产生大量的碎片。本篇文章我们…

MAC电脑的JDK、MAVEN配置及IDEA激活

1、JDK配置环境 vim ~/.bash_profile # 添加 Java 目录&#xff0c;类路径和指令路径的配置&#xff0c;若已存在则用目标值覆盖 export JAVA_HOME/Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/Contents/Home export CLASSPATH.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/…

Oracle单实例静默安装

oracle 11g单实例静默安装 在CentOS上静默安装Oracle数据库 引言 在企业环境中&#xff0c;自动化和标准化是提高效率的关键。静默安装&#xff08;也称为无人值守安装&#xff09;是一种无需人工干预的安装方法&#xff0c;适用于大规模部署或需要重复安装的场景。本文将介…

【KEIL那些事 4】CMSIS缺失!!!!导致不能编译!!!!软件自带芯片下载缓慢!!!!!!快速下载芯片包!!!!!

安装了keli发现emmm&#xff0c;CMSIS缺失&#xff01;&#xff01;&#xff01;&#xff01;不能编译&#xff0c;&#xff0c;&#xff0c;自带下载芯片缓慢&#xff0c;&#xff0c;&#xff0c;官网下载emmm&#xff0c;竟然不带动的&#xff01;&#xff01;&#xff01;&…

MySQL根据.idb数据恢复脚本,做成了EXE可执行文件

文章目录 1.代码2.Main方法打包3.Jar包打成exe可执行文件4.使用&#xff08;1.&#xff09;准备一个表结构一样得数据库&#xff08;2.&#xff09;打开软件&#xff08;3.&#xff09;输入路径 5.恢复成功 本文档只是为了留档方便以后工作运维&#xff0c;或者给同事分享文档内…

查看Chrome安装路

谷歌Google浏览器查看安装路径&#xff0c;浏览器Google Chrome浏览器查看安装路径 chrome://version/ 来源&#xff1a;笔记云

(数据结构)单链表——C语言

目录 1 概念与结构 1.1 结点 1.2 链表的性质 2 实现单链表 2.1打印SLPrint 2.2申请一个结点SLBuyNode 2.3尾插SLPushBack 2.4头插SLPushfront 2.5尾删SLPopBack 2.6头删SLPopfront 2.7查找结点位置SLFindNode 2.8在pos位置插入SLInsert 2.9在pos节点之后插入SLInse…

2024HarmonyOS应用开发者高级认证 最新题库第二部分

单选题 1.以下哪个装饰器用来表示并发共享对象。&#xff08;D&#xff09; AShared BState CStyle DSendable 2.hiAppEvent提供的Watcher接口&#xff0c;需要订阅到OS的崩溃事件&#xff0c;正确的实现方式(选下面这个) hiAppEvent.addWatcher({ name:"watcher&…

探索网页组件化:原生JavaScript动态加载HTML与iframe的使用与比较

在网页设计中&#xff0c;将内容作为组件动态加载到页面上是一种提高用户体验和页面性能的有效手段。本文将详细介绍两种实现动态内容加载的方法&#xff1a;使用原生JavaScript动态加载HTML和使用iframe&#xff0c;并对比它们的使用方式和优缺点。 原生JavaScript动态加载HTM…

[论文笔记]HERMES 3 TECHNICAL REPORT

引言 今天带来论文HERMES 3 TECHNICAL REPORT&#xff0c;这篇论文提出了一个强大的工具调用模型&#xff0c;包含了训练方案介绍。同时提出了一个函数调用标准。 为了简单&#xff0c;下文中以翻译的口吻记录&#xff0c;比如替换"作者"为"我们"。 聊天模…

RISC-V笔记——内存模型总结

1 前言 Memory consistency model定义了使用Shared memory(共享内存)执行多线程(Multithread)程序所允许的行为规范。RISC-V使用的内存模型是RVWMO(RISC-V Weak Memory Ordering)&#xff0c;RVWMO内存模型是根据全局内存顺序(global memory order)定义的&#xff0c;全局内存…

简单有效修复d3d9.dll错误,11种d3d9.dll错误详细解决办法教程

当你遇到d3d9.dll文件丢失的问题时&#xff0c;可以通过今天的这篇文章详细的步骤来尝试修复这个问题&#xff0c;今天将教大家十一种d3d9.dll丢失修复的方法。 1. 重新安装DirectX以恢复d3d9.dll d3d9.dll是DirectX的一部分&#xff0c;因此重新安装DirectX通常可以解决d3d9.…

proguard对java代码进行混淆加密。并进行反编译测试,后续可配合classfinal进行使用

文章目录 1.插件混淆&#xff08;1.&#xff09;pom配置&#xff08;2.&#xff09;混淆配置&#xff08;3.&#xff09;打包 2.反编译查看效果&#xff08;1.&#xff09;工具下载&#xff08;2.&#xff09;反编译对比 3.启动测试4.功能测试5.二次加密 本文档只是为了留档方便…

【ChatGPT插件漏洞三连发之一】未授权恶意插件安装

漏洞 要了解第一个漏洞&#xff0c;我们必须首先向您展示 OAuth 身份验证的工作原理&#xff1a; 假设您是 Dan&#xff0c;并且您想使用您的 Facebook 帐户连接到 Example.com。当您点击“使用Facebook登录”时会发生什么&#xff1f; 在步骤 2-3 中&#xff1a; 在 Dan 单…

2024成为自动化测试的7种技能!

随着敏捷和DevOps等新时代项目开发方法逐渐取代旧的瀑布模型&#xff0c;测试需求在业界不断增长。测试人员现在正在与开发人员一起工作&#xff0c;自动化测试在许多方面极大地取代了手动测试。如果您是自动化测试领域的新手&#xff0c;刚雇用您的组织将期望您快速&#xff0…

java线程的几种状态

线程的所有状态 NEW: 安排了工作, 还未开始行动RUNNABLE: 可工作的. 又可以分成正在工作中和即将开始工作. BLOCKED: 这几个都表示排队等着其他事情 WAITING: 这几个都表示排队等着其他事情TIMED_WAITING: 这几个都表示排队等着其他事情TERMINATED: 工作完成了. 线程状态和状…