C++学习笔记-友元函数的定义与使用

一、引言

在C++中,友元函数(Friend Function)是一个独特而强大的特性,它打破了类的封装性,允许一个或多个非成员函数访问类的私有(private)和保护(protected)成员。尽管这种特性在某些情况下可能引发争议,因为它违反了面向对象编程中的封装原则,但在需要高效访问类内部状态或实现某些特定设计时,友元函数却又非常适用。

1.1 封装与友元函数的关系

在面向对象编程(OOP)中,封装是一种将数据(属性)与操作这些数据的函数(方法)绑定在一起的方法。封装的主要目的是隐藏类的内部实现细节,只对外提供有限的接口供外部使用。然而,在某些情况下,我们可能希望允许某些特定的非成员函数访问类的私有成员。这时,友元函数就显得尤为重要了。

1.2 友元函数的概念

友元函数不是类的成员函数,但它可以访问类的所有私有(private)和保护(protected)成员。要使一个函数成为类的友元,需要在类定义中声明该函数为友元。友元函数可以是普通函数,也可以是其他类的成员函数。

二、友元函数的定义与使用

2.1 定义友元函数

在类定义中,使用friend关键字可以声明一个或多个友元函数。友元函数的声明可以放在类的任何位置(但通常放在类定义的开始部分),但它们的定义(实现)必须在类定义之外进行。

示例:

#include <iostream>  class MyClass {  
private:  int value;  public:  MyClass(int val) : value(val) {}  // 声明友元函数  friend void printValue(const MyClass& obj);  
};  // 定义友元函数  
void printValue(const MyClass& obj) {  std::cout << "Value: " << obj.value << std::endl;  
}  int main() {  MyClass myObj(10);  printValue(myObj); // 输出: Value: 10  return 0;  
}

在上面的示例中,printValue函数被声明为MyClass的友元函数,因此它可以访问MyClass对象的私有成员value。

2.2 友元函数的特性

非成员函数:友元函数不是类的成员函数,因此它不会隐式地接收类的this指针。
访问权限:友元函数可以访问类的所有成员,包括私有和保护成员。
作用域:友元函数的作用域不是类的作用域,而是定义它的作用域。但是,它可以通过类的对象来访问类的成员。
数量不限:一个类可以有任意数量的友元函数。
不继承:友元关系不是继承的。如果类B是类A的友元,那么类B的子类不会自动成为类A的友元。

2.3 友元成员函数

除了普通函数外,类的成员函数也可以被声明为其他类的友元函数。这允许一个类的成员函数访问另一个类的私有成员。

示例:

#include <iostream>  class MyClassB; // 前向声明  class MyClassA {  
private:  int value;  public:  MyClassA(int val) : value(val) {}  // 声明MyClassB的成员函数为友元  friend void MyClassB::printValue(const MyClassA& obj);  
};  class MyClassB {  
public:  void printValue(const MyClassA& obj) {  std::cout << "Value from MyClassA: " << obj.value << std::endl;  }  
};  int main() {  MyClassA myObjA(20);  MyClassB myObjB;  myObjB.printValue(myObjA); // 输出: Value from MyClassA: 20  return 0;  
}

注意,在声明友元成员函数时,需要先对目标类进行前向声明,因为编译器在解析MyClassA的类定义时需要知道MyClassB是一个类名。

三、友元函数的使用场景

3.1. 重载操作符

友元函数最常见的用途之一是用于重载操作符,特别是当操作符需要访问类的私有或保护成员时。例如,在自定义的复数类(Complex)中,你可能想要重载<<操作符以便能够直接将复数对象输出到流中。由于输出操作需要访问复数对象的实部和虚部(这些通常是私有成员),因此将<<操作符定义为复数类的友元函数是一个很好的选择。

3.2. 辅助函数

有时,我们可能需要一些辅助函数来帮助实现类的功能,但这些函数并不适合作为类的成员函数。例如,如果有一个表示二维图形的类(如圆形或矩形),我们可能需要一个函数来计算两个图形是否相交。这样的函数可能需要访问图形的私有成员(如中心坐标和半径或边界),但将这些功能作为类的成员函数可能并不合适,因为它们并不是图形对象本身的操作。这时,可以将这些辅助函数声明为类的友元函数。

3.3. 模板类中的友元

在模板类中,友元函数的使用变得更加复杂但也更加有用。模板类的友元可以是另一个模板类或非模板类,甚至可以是模板函数。这允许模板类与非模板代码或不同类型的模板代码之间进行更紧密的交互。例如,你可能有一个模板容器类,并希望提供一个模板化的友元函数来执行某种类型的算法,这个算法需要访问容器的内部数据结构。

3.4. 访问控制绕过

虽然这通常不是推荐的做法,但在某些特殊情况下,友元函数可以用来绕过类的访问控制,以提供对私有成员的访问。这可以在需要优化性能(如避免通过公共接口访问时产生的额外开销)或实现特定设计模式(如访问者模式)时非常有用。然而,过度使用友元可能会破坏封装性,使代码更难理解和维护。

3.5. 跨类访问

友元函数还可以用于实现跨类访问,即一个类的友元函数可以访问另一个类的私有成员。这在设计需要紧密协作的类时特别有用,例如,在某些设计模式(如代理模式或装饰器模式)中,一个类的行为可能依赖于另一个类的内部状态。

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

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

相关文章

Springboot+Maven多模块项目开发

SpringbootMaven多模块项目开发 前言示例项目建设Parent项目Common模块ModuleOne模块特别说明 参考&#xff1a; 前言 1.多模块项目的好处&#xff1a; 代码复用 一个后端项目的entity、dao、service代码需要用到前端服务&#xff0c;还需要用到后台管理&#xff0c;通过多模…

Wordpress安装到win10(2024年7月)

目录 1.wordpress介绍 2下载应用 2.1.wordpress 2.2XAMPP 2.3 PHPmyadmin 3.配置应用 3.1XAMPP进程 3.2 文件配置 3.3 phpmyadmin配置 4.配置网页 4.1 数据库创建 4.2 安装wordpress 5.进入面板 6.总结 1.wordpress介绍 WordPress是一个开源内容管理系统&#xff0…

Java台球厅助教教练预约上门到店系统源码

&#x1f3b1;一杆在手&#xff0c;天下我有&#xff01;台球助教教练预约系统&#xff0c;让球技飙升不是梦&#x1f680; &#x1f3af;【开篇&#xff1a;台球爱好者的福音来啦&#xff01;】&#x1f3af; 还在为找不到合适的台球教练而烦恼吗&#xff1f;或是想要在家就…

Django Nginx + uWSGI 安装配置

Django Nginx + uWSGI 安装配置 本文将详细介绍如何在Linux服务器上安装和配置Django、Nginx和uWSGI。这些技术通常一起使用来部署高性能的Django应用程序。我们将分步骤进行,确保您能够顺利地完成整个过程。 1. 安装Python和pip 在开始之前,请确保您的系统上安装了Python…

【C#学习笔记】数组

在C#中&#xff0c;数组是一种数据结构&#xff0c;用于存储一系列相同类型的元素。数组在C#中非常常见&#xff0c;因为它们提供了高效的数据存储和访问方式。下面&#xff0c;我将从基础概念到高级用法&#xff0c;为您详细解释C#中的数组。 基础概念 定义&#xff1a; 数组…

抽象代数精解【4】

文章目录 子群难点与例子中心化子与正规化子定义性质与正规化子的关系应用 det概述两个矩阵乘积的行列式等于这两个矩阵行列式的乘积 参考文献 子群 难点与例子 在 z 10 中&#xff0c;令 H { 2 ˉ , 4 ˉ , 6 ˉ , 8 ˉ } , 证明&#xff1a; H 中关于剩余类的乘法构成群&am…

社交圈子聊天交友系统搭建社交app开发:陌生交友发布动态圈子单聊打招呼群聊app介绍

系统概述 社交圈子部天交友系统是一个集成即时通讯、社区互动、用户管理等功能的在线社交平台。它支持用户创建个人资料&#xff0c;加入兴趣围子&#xff0c;通过文字、图片、语音、视频等多种方式进行交流&#xff0c;满足用户在不同场景下的社交需求 核心功能 -&#xff0c;…

【C#学习笔记】变量、变量类型

在C#中&#xff0c;变量是存储数据的容器&#xff0c;每个变量都有其特定的数据类型&#xff0c;这决定了变量可以存储的数据类型和大小。以下是关于C#中变量的由浅入深的详细解释&#xff0c;并附带代码示例和解释&#xff1a; 基础概念 定义&#xff1a; 变量是存储数据的容…

使用 abap2xlsx 给SMW0上传的模版填充值

入参 IS_DATA OBJ_ID CHAR SAP WWW 网关对象名 DEFAULT_FILE_NAME STRING Default Extension DEFAULT_EXTENSION STRING Default File Name FILE_FILTER STRING FILENAME STRING 下载文件地址 IT_CELL ROW INT4 行号 COLUMN INT4 列号 VALUE STRING 单…

Matlab编程资源库(1)选择结构

一、if语句 在 MATLAB 中&#xff0c; if 语句有 3 种格式。 (1) 单分支 if 语句&#xff1a; if 条件 语句组 end 当条件成立时&#xff0c;则执行语句组&#xff0c;执行完之后&#xff0c; 继续执行 if 语句的后继语句&#xff0c;若条件不成 立&#xff0c;则直接执…

金融无风险套利:逆回购

金融创新与逆回购 在当今金融创新不断涌现的时代&#xff0c;逆回购作为一种无风险套利工具&#xff0c;逐渐走进了大众的视野。它不仅为投资者提供了一种新的理财方式&#xff0c;也为金融专业人士提供了一个研究和应用的新领域。本文将带领读者深入了解逆回购的基本概念、操…

人生低谷来撸C#--015 C# 属性(Property)

1、概念 在C#中&#xff0c;属性&#xff08;Property&#xff09;是一种特殊的成员&#xff0c;它提供了一种灵活的机制来访问和修改对象的状态&#xff08;即类的字段&#xff09;。属性结合了字段和方法的特性&#xff0c;使得数据的访问和修改更加安全和便捷。下面我用一个…

Qt源码交叉编译带openssl的Qt版本

一.背景 近期项目由于对接的后台服务是https的&#xff0c;之前交叉编译的Qt是不带openssl的&#xff0c;为了能支持https&#xff0c;必须要重新编译Qt。 二.环境 环境准备&#xff1a; Ubuntu版本 &#xff1a;18.04&#xff1b; openssl 版本&#xff1a;1.1.1.g&#xff1b…

C/C++的堆栈内存分配详解

在C/C编程中&#xff0c;内存管理是至关重要的一个方面。理解内存的分配方式有助于编写高效、可靠的程序&#xff0c;C/C主要使用两种内存分配方式&#xff1a;堆&#xff08;heap&#xff09;和栈&#xff08;stack&#xff09;。这两者在管理方式、性能和使用场景上都有显著区…

python计算PMF、PDF、CDF、PPF、KDE介绍

目录 1. 总括1.1 绘图示例1.2 概念介绍1. PMF (Probability Mass Function)2. PDF (Probability Density Function)3. CDF (Cumulative Distribution Function)4. PPF (Percent Point Function)5. KDE (Kernel Density Estimation)1. 总括 1.1 绘图示例 上图展示了PMF、PDF、C…

物联网精密空调监控指标解读:松越_TCP7022EX_精密空调

监控易是一款专业的IT和物联网设备监控软件&#xff0c;能够实时监控各类IT资源和物联网设备的运行状态&#xff0c;确保系统的稳定运行。在物联网精密空调领域&#xff0c;监控易对松越_TCP7022EX_精密空调进行了全面的监控&#xff0c;以下是对其监控指标的详细解读。 监控指…

天工Godwork AT 5.2.6 GodWork2D 2.1.5 GodWork EOS 2.1实景三维建模软件

天工Godwork AT 5.2.6/GodWork2D 2.1.5/GodWork EOS 2.1实景三维建模软件 获取安装包联系邮箱:2895356150qq.com 本介绍用于学习使用&#xff0c;如有侵权请您联系删除&#xff01; 1.自主研发的平差技术&#xff0c;平差模块不依赖PATB、Bingo等国外技术 2.采用特征匹配&…

华媒舍:6个媒体宣发套餐,快速突破传播界限

在当今信息爆炸的社会中&#xff0c;有效地传播自己的信息变得愈发困难。特别是对于媒体宣发来说&#xff0c;如何在市场竞争激烈的情况下突破传播界限&#xff0c;让自己的消息传达给更多的人&#xff0c;这是每个企业和个人都面临的难题。 为了解决这个问题&#xff0c;我们推…

无人机之在农业上的用途

随着无人机技术的发展&#xff0c;农业现代化也迎来了崭新局面&#xff0c;田间随处可见无人机矫健的身影。当农业遇上科技&#xff0c;变革正悄然进行。农业无人机主要应用于农业、种植业、林业等行业。在使用过程中&#xff0c;其功能和作用并不单一&#xff0c;一般用于种植…

libtins初探-抓包嗅探

libtin 一、概述1. 可移植性2. 特性 二、基础知识1. PDU2. 地址类3. 地址范围类4. 网络接口5. 写pcap文件 三、嗅探1.嗅探基础2. 嗅探器配置3. 循环嗅探4. 使用迭代器嗅探6. 包对象7. 读取pcap文件8. 包的解析 四、发送包1. 发送网络层pdu2. 发送链路层pdu3. 发送和接收响应校验…