【C++入门】友元函数详解(定义、实现、优缺点)

2023-11-15

1、友元函数/友元类定义

(1)在类中用friend关键字去声明函数/类,则这个函数/类就会变成友元函数/友元类;
(2)友元函数/友元类的声明位置没有要求,可以在private、protected、public权限区,效果都是一样的;
(3)友元函数/友元类是单向的,A在B类中被声明为友元函数/友元类,表示A是B的友元函数/友元类,但B不是A的友元类函数/友元类;
(4)友元函数/友元类具有和类成员一样的权限,可以访问protected和private权限的成员,但不是类的成员;
(5)友元函数在类中声明时用friend修饰,但是在定义时不需要用friend修饰;
(6)友元函数不能被继承:父类的友元函数,继承后并不会成为子类的友元函数;
(7)友元函数不具有传递性:A类和B类都是C类的友元类,但是A类和B类并不是友元类;

2、友元函数、类成员函数、非友元函数的区别

(1)友元函数和非友元函数都是类外函数,不是类的成员函数,所以函数内不能使用this指针来表示类的对象;
(2)友元函数相比于非友元函数,友元函数具有类成员函数一样的权限,可以访问类的protected和private权限下的成员,而非友元函数不可以;
(3)友元函数不是类的成员,所以不能用类的对象去访问友元函数;

3、友元函数的两种实现

3.1、友元函数是普通全局函数

#include <iostream>

using namespace std;


class Person
{
private:
	int age;

public:
	Person(){};
	Person(int x);

	//声明print是友元函数
	friend void print(Person &pn);
};

Person::Person(int x)
{
	this->age = x;
}


void print(Person &pn)
{
	//因为print是Person类的友元函数,所以在内部可以访问Person类的私有成员age
	cout << "age=" << pn.age << endl;
}

int main(void)
{
	Person p(22);
	
	print(p);

	return 0;
}

3.2、友元函数是其他类的成员函数

#include <iostream>

using namespace std;

class Person;

class Man
{
public:
	void print(Person &pn);

};

class Person
{
private:
	int age;

public:
	Person(){};
	Person(int x);

	//声明print是友元函数
	friend void Man::print(Person &pn);
};

Person::Person(int x)
{
	this->age = x;
}

void Man::print(Person &pn)
{
	//因为print是Person类的友元函数,所以在内部可以访问Person类的私有成员age
	cout << "Man::print" << endl;
	cout << "age=" << pn.age << endl;
}

int main(void)
{
	Person p(22);
	Man M;
	
	M.print(p);

	return 0;
}

4、友元类

4.1、示例代码

#include <iostream>
#include <string>

using namespace std;

class Person;

class Man
{
private:
	string name;

public:
	Man(){};
	Man(string myname)
	{
		this->name = myname;
	}
	
	void print_Man(Person &pn);

	//声明Person类是友元类
	friend class Person;

};

class Person
{
private:
	int age;

public:
	Person(){};
	Person(int x)
	{
		this->age = x;
	}
	
	void print_Person(Man &pn);

	//声明Man类是友元类
	friend class Man;
};

void Man::print_Man(Person &pn)
{
	//因为Man类是Person类的友元函数,Man的成员函数也可以访问Person类的私有成员
	cout << "Man::print" << endl;
	cout << "age=" << pn.age << endl;
}

void Person::print_Person(Man &pn)
{
	//因为Person类是Man类的友元函数,Person的成员函数也可以访问Man类的私有成员
	cout << "Person::print" << endl;
	cout << "name=" << pn.name << endl;
}

int main(void)
{
	Person p(22);
	Man M("linux");

	//Person和Man互为友元类
	p.print_Person(M);
	M.print_Man(p);

	return 0;
}

4.2、友元函数和友元类的比较

(1)当A类被声明为B类的友元类时,则A类中的所有成员函数都可以访问B类private和protected权限成员;
(2)A类和B类可以都声明对方为友元类,则A类和B类互为友元类,都可以访问对方类受保护的成员;
(3)类中包含一个或者多个成员函数,将类声明为友元类,则相当于一次声明了多个友元函数;
总结:友元类可以批量的声明友元函数;

5、友元函数/友元类的优缺点

(1)缺点:友元函数不是类的成员但是却具有成员的权限,可以访问类中受保护的成员,这破坏了类的封装特性和权限管控;
(2)优点:可以实现类之间的数据共享;比如上面互为友元类,则可以互相访问对方受保护的成员;
总结:友元函数是一种破坏封装特性的机制,可以让程序员写代码更灵活,但是不能滥用;

6、不能用友元函数重载的运算符

参考博客:《【C++入门】不能重载为友元函数的4个运算符(=, ->, [ ], ( ))》

推荐

我会在C++专栏持续根据更新C++相关的知识点,这里也给大家推荐一款学习C++的神器,我也是在用这一款神器在学习C++。
链接:学习神器跳转
如果你是想入门C++这门语言或者是找C++岗位的工作,都推荐你试试这个网站,里面有针对C++知识点的选择题、编程题,更有C++岗位的面试题,还可以在里面交流行业信息
在这里插入图片描述
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C++入门】友元函数详解(定义、实现、优缺点) 的相关文章

  • 编译时运算符

    有人可以列出 C 中可用的所有编译时运算符吗 C 中有两个运算符 无论操作数如何 它们的结果始终可以在编译时确定 它们是sizeof 1 and 2 当然 其他运算符的许多特殊用途可以在编译时解决 例如标准中列出的那些整数常量表达式 1 与
  • 如何使用 C# 中的参数将用户重定向到 paypal

    如果我有像下面这样的简单表格 我可以用它来将用户重定向到 PayPal 以完成付款
  • WCF RIA 服务 - 加载多个实体

    我正在寻找一种模式来解决以下问题 我认为这很常见 我正在使用 WCF RIA 服务在初始加载时将多个实体返回给客户端 我希望两个实体异步加载 以免锁定 UI 并且我想利用 RIA 服务来执行此操作 我的解决方案如下 似乎有效 这种方法会遇到
  • 秒表有最长运行时间吗?

    多久可以Stopwatch在 NET 中运行 如果达到该限制 它会回绕到负数还是从 0 重新开始 Stopwatch Elapsed返回一个TimeSpan From MSDN https learn microsoft com en us
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • 使用 WebClient 时出现 System.Net.WebException:无法创建 SSL/TLS 安全通道

    当我执行以下代码时 System Net ServicePointManager ServerCertificateValidationCallback sender certificate chain errors gt return t
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • 重载<<的返回值

    include
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co

随机推荐

  • 国际MES供应商与产品大全

    最近花了一点时间 将国际上知名的MES厂商和其产品整理了一下 如下 ABB ABB 苏黎世 瑞士 是一个240亿美元的自动化和电力技术的全球业务的供应商 它的制造软件利用其控制及自动化产品通用解决方案的一部分 其系统800xa控制体系结构
  • Android 自定义播放暂停按钮图片

    Android 自定义播放暂停按钮图片 在开发Android应用程序时 我们经常需要使用播放暂停按钮来控制媒体播放器的状态 虽然Android提供了默认的播放暂停按钮 但有时候我们希望根据设计需求自定义这些按钮的外观 在本文中 我将详细介绍
  • 嵌入式毕设分享 自动晾衣架设计与实现(源码+硬件+论文)

    文章目录 0 前言 1 主要功能 2 硬件设计 原理图 3 核心软件设计 4 实现效果 5 最后 0 前言 这两年开始毕业设计和毕业答辩的要求和难度不断提升 传统的毕设题目缺少创新和亮点 往往达不到毕业答辩的要求 这两年不断有学弟学妹告诉学
  • 解决tmux启动「can't create socket」的问题

    Tmux是终端重度用户的好帮手 你再也不用担心以下问题 任务运行一半要下班 发现忘记使用nohup 网络不稳定 终端会掉线 有人找我开会 切换有线 无线会掉线 我入职以后 一直在开发机里面使用tmux和screen 在我发现tmux之前 最
  • Java的循环

    目录 1 while循环 2 do while循环 3 for 循环 1 while循环 while循环结构 语法结构 初始值 while 条件 循环操作代码块 迭代代码 执行规律 1 首先执行一次初始值 2 然后判断条件 如果条件为tru
  • ESP32的WIFI的STA模式&调控ESP32蓝牙和WIFI发射功率

    以下相关API接口的定义可进入l乐鑫官方查看 Wi Fi 库 ESP32 ESP IDF 编程指南 v4 4 文档 STA模式配置过程 include
  • springboot 获取当前日期_Spring Boot获取时间

    运行环境新建测试类 package com wusiyao websockets service import org springframework stereotype Service import java text SimpleDa
  • 【Linux后端服务器开发】常用开发工具

    目录 一 apt yum 二 gcc g 三 make makefile 四 vi vim 五 gdb 一 apt yum apt 和 yum 都是在Linux环境下的软件包管理器 负责软件的查找 安装 更新与卸载 apt 是Ubuntu系
  • 小程序经典案例

    1 上拉触底事件 data colorList isloding false getColors this setData isloding true 需要展示 loading 效果 wx showLoading title 数据加载中 w
  • Java学习笔记 03

    相关文章 Java学习笔记 01 概论 Java学习笔记 02 快速之旅 Java环境配置及HelloWorld程序 引言 写这篇文章 主要是为了以后能快速复习Java的基础语法 同时 帮助有C 等语言基础的同学快速入门Java 目录 一
  • SmartFusion从FPGA到ARM系列教程

    前言 本系列教程 将会以Microsemi SmartFusion一代芯片A2F200M3F为例 简单介绍片上ARM Cortex M3 硬核 MCU 基本外设的使用 及其与FPGA逻辑模块进行交互的示例 在学习片上硬核ARM Cortex
  • 网上阅卷系统php源码,又开源了,网上阅卷系统自动识别功能代码

    想让自己轻松点就要让计算机多为你做点 前几天一个朋友找到我让我做一个网上阅卷系统 就是实现这么几个功能 高速扫描仪扫描试卷后得到一张一张的图片 软件的功能就是处理图片 计算成绩 再详细点就是自动识别考生涂的学号 自动识别考生的选择题答案并记
  • css设计引言,HTML5与CSS3设计模式 引言(3)

    引言 3 2 代码清单2 浮动下沉首字示例 HTML pclass hanging indent spanclass hanging dropcap H span anging Dropcap p CSS hanging indent pa
  • 2022-渗透测试-git提权(Linux)

    目录 1 什么是提权 2 git提权命令 3 git的使用 1 什么是提权 提权就是通过各种办法和漏洞 提高自己在服务器中的权限 以便控制全局 利用漏洞的最终目的是获取被测系统的最高权限 即Windows中管理员账户的权限 或Linux中r
  • C++自定义connect超时时间——非阻塞套接字法

    一 代码 include
  • 深圳大学数据库系统实验 Leasing Luxury Database system 基于PHP,MySQL,Web三件套

    本实验要求搭建一个手袋租聘的数据库系统 并实现以下要求 创建一个数据库 可以记录客户数据 手袋数据 租聘数据 设计者数据 用户可以提供自己的邮箱地址 邮寄地址 信用卡号码 来注册租聘网站 数据库要展示所有课租聘的手袋 已被租聘的手袋用户不能
  • java基础之Map集合

    Map集合 HashMap 数据结构 HashMap数据存放过程 HashMap 线程安全问题 多线程不安全案例 Collections synchronizedMap new HashMap 保证Map安全 HashTable 数据结构
  • 【论文译文】VQVAE2

    译文仅供参考 原文是pdf 想下载的话可以戳 http www gwylab com pdf vqvae2 chs pdf
  • python DVWAXSSPOC练习

    XSS反射性低难度 数据包 GET dv vulnerabilities xss r name 3Cscript 3Ealert 28 27xss 27 29 3C 2Fscript 3E HTTP 1 1 Host 10 9 75 161
  • 【C++入门】友元函数详解(定义、实现、优缺点)

    1 友元函数 友元类定义 1 在类中用friend关键字去声明函数 类 则这个函数 类就会变成友元函数 友元类 2 友元函数 友元类的声明位置没有要求 可以在private protected public权限区 效果都是一样的 3 友元函