【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++ 维护子类对象的混合集合

    如果我在这里错过了一个相当基本的概念 我很抱歉 但我正在尝试弄清楚如何维护多个类类型的集合 所有类类型都派生自同一个父类 并且在检索它们时仍然可以访问它们的特定于子类的方法从集合中 作为上下文 我有一个基类 BaseClass 和许多类 例
  • 静态只读字符串数组

    我在我的 Web 应用程序中使用静态只读字符串数组 基本上数组有错误代码 我将所有类似的错误代码保存在一个数组中并检查该数组 而不是检查不同常量字符串中的每个错误代码 like public static readonly string m
  • 为什么在连接两个字符串时 Python 比 C 更快?

    目前我想比较 Python 和 C 用来处理字符串的速度 我认为 C 应该比 Python 提供更好的性能 然而 我得到了完全相反的结果 这是 C 程序 include
  • 计算 XML 中特定 XML 节点的数量

    请参阅此 XML
  • 以编程方式读取 SQL Server 查询计划建议的 SQL 特定执行的索引?

    如果我在 SSMS 中运行此命令 set showplan xml on GO exec some procedure arg1 arg2 arg3 GO set showplan xml off GO 我获得查询执行中涉及的完整调用堆栈的
  • 在c#中执行Redis控制台命令

    我需要从 Redis 控制台获取 客户端列表 输出以在我的 C 应用程序中使用 有没有办法使用 ConnectionMultiplexer 执行该命令 或者是否有内置方法可以查找该信息 CLIENT LIST是 服务器 命令 而不是 数据库
  • 为什么pow函数比简单运算慢?

    从我的一个朋友那里 我听说 pow 函数比简单地将底数乘以它的指数的等价函数要慢 例如 据他介绍 include
  • IdentityServer 4 对它的工作原理感到困惑

    我阅读和观看了很多有关 Identity Server 4 的内容 但我仍然对它有点困惑 因为似乎有很多移动部件 我现在明白这是一个单独的项目 它处理用户身份验证 我仍然不明白的是用户如何注册它 谁存储用户名 密码 我打算进行此设置 Rea
  • 如何在C(Linux)中的while循环中准确地睡眠?

    在 C 代码 Linux 操作系统 中 我需要在 while 循环内准确地休眠 比如说 10000 微秒 1000 次 我尝试过usleep nanosleep select pselect和其他一些方法 但没有成功 一旦大约 50 次 它
  • 如何判断计算机是否已重新启动?

    我曾经使用过一个命令行 SMTP 邮件程序 作为试用版的限制 它允许您在每个 Windows 会话中最多接收 10 封电子邮件 如果您重新启动计算机 您可能还会收到 10 个以上 我认为这种共享软件破坏非常巧妙 我想在我的应用程序中复制它
  • 如何使用 Castle Windsor 将对象注入到 WCF IErrorHandler 实现中?

    我正在使用 WCF 开发一组服务 该应用程序正在使用 Castle Windsor 进行依赖注入 我添加了一个IErrorHandler通过属性添加到服务的实现 到目前为止一切正常 这IErrorHandler对象 一个名为FaultHan
  • 从客户端访问 DomainService 中的自定义对象

    我正在使用域服务从 Silverlight 客户端的数据库中获取数据 在DomainService1 cs中 我添加了以下内容 EnableClientAccess public class Product public int produ
  • C# 存档中的文件列表

    我正在创建一个 FileFinder 类 您可以在其中进行如下搜索 var fileFinder new FileFinder new string C MyFolder1 C MyFolder2 new string
  • IQueryable 单元或集成测试

    我有一个 Web api 并且公开了一个端点 如下所示 api 假期 name name 这是 Web api 的控制器 get 方法 public IQueryable
  • 在视口中查找 WPF 控件

    Updated 这可能是一个简单或复杂的问题 但在 wpf 中 我有一个列表框 我用一个填充数据模板从列表中 有没有办法找出特定的数据模板项位于视口中 即我已滚动到其位置并且可以查看 目前我连接到了 listbox ScrollChange
  • 在mysql连接字符串中添加应用程序名称/程序名称[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我正在寻找一种解决方案 在连接字符串中添加应用程序名称或程序名称 以便它在 MySQL Workbench 中的 客户端连接 下可见 SQL
  • 保护 APK 中的字符串

    我正在使用 Xamarin 的 Mono for Android 开发一个 Android 应用程序 我目前正在努力使用 Google Play API 添加应用内购买功能 为此 我需要从我的应用程序内向 Google 发送公共许可证密钥
  • C++ 中的双精度型数字

    尽管内部表示有 17 位 但 IEE754 64 位 浮点应该正确表示 15 位有效数字 有没有办法强制第 16 位和第 17 位为零 Ref http msdn microsoft com en us library system dou
  • WebBrowser.Print() 等待完成。 。网

    我在 VB NET 中使用 WebBrowser 控件并调用 Print 方法 我正在使用 PDF 打印机进行打印 当调用 Print 时 它不会立即启动 它会等到完成整个子或块的运行代码 我需要确保我正在打印的文件也完整并继续处理该文件
  • 在 Windows Phone silverlight 8.1 上接收 WNS 推送通知

    我有 Windows Phone 8 1 silverlight 应用程序 我想使用新框架 WNS 接收通知 我在 package appxmanifest 中有

随机推荐

  • 国际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 友元函