C++友元函数friend使用的学习总结

news2024/11/25 17:51:39

C++友元函数friend使用的学习总结

    • 1. 友元函数简介
      • 1.1 使用友元函数的目的
      • 1.2 友元函数的三种实现方法
    • 2.全局函数做友元
    • 3.类做友元
    • 4.成员函数做友元
      • 注意!

1. 友元函数简介

1.1 使用友元函数的目的

允许一个函数或者类访问另一个类中的私有成员,使得两个类可以共享同一数据。

举个例子,有亲戚去你家拜访,那么客厅是所有人可见的(public类),但自己的房间就不太方便了(private类),不过自己的基友或者闺蜜可以进入你的房间,这就需要友元函数,这就是friend。

1.2 友元函数的三种实现方法

  • 全局函数做友元
  • 类做友元
  • 成员函数做友元

2.全局函数做友元

​ 全局函数做友元,就是在类外定义一个全局函数,该全局函数传入一个类的指针或者引用。该类的公共成员可以直接调用,若将该全局函数作为友元写入类中,该函数就可调用私有成员。

代码如下:

#include <iostream>
using namespace std;

class House {
	//设置全局函数bestFriend是类的好朋友,可以访问类中的私有成员m_BedRoom
	friend void bestFriend(House& house);

public:
	House()
	{
		m_SittingRoom = "客厅";
		m_BedRoom = "卧室";
	}

	string m_SittingRoom;

private:
	string m_BedRoom;	//私有成员,卧室
};

//全局函数实现
void bestFriend(House &house)	//引用或者指针都可以
{
	cout << "好朋友全局函数 正在访问: " <<house.m_SittingRoom << endl;
	cout << "好朋友全局函数 正在访问: " <<house.m_BedRoom<< endl;
}

void test01()
{
	House house;	//创建一个House类对象
	bestFriend(house);		//调用全局函数访问类中公有和私有成员
}

int main() {
	test01();
	return 0;
}

其中,主要代码就一行:

friend void bestFriend(House& house);

​在这里,设置全局函数bestFriend()是House类的友元,然后就可以访问类中的私有成员。

如果没有声明该函数为House类友元,则程序会出现如下报错:
未添加友元全局函数

设置友元后的代码运行结果:
添加友元全局函数

3.类做友元

​类做友元,就是用类B中的函数去调用另一个类A中的私有成员,这需要在类A中将类B做为友元写入

#include <iostream>
using namespace std;

class House
{
	//设置BestFriend为House类的友元,可以调用House的私有成员
	friend class BestFriend;
public:
	House()
	{
		m_SittingRoom = "客厅";
		m_BedRoom = "卧室";
	}
	string m_SittingRoom;

private:
	string m_BedRoom;		//私有成员,卧室
};

class BestFriend 
{
public:
	BestFriend()
	{
		//创建House对象
		house = new House;
	}
	void visit()	//参观函数,访问House中的属性
	{
		cout << "好朋友正在访问: " << house->m_SittingRoom << endl;
		cout << "好朋友正在访问: " << house->m_BedRoom << endl;
	}
	House* house;
};

void test01()
{
	BestFriend bf;		//创建好友对象
	bf.visit();			//调用好友对象中的函数来访问House中的成员
}

int  main()
{
	test01();
	return 0;
}

其中,主要代码为:

friend class BestFriend;

​在这里,设置BestFriend为House类的友元,可以调用House的私有成员。

4.成员函数做友元

成员函数做友元,就是如果要在类B中使用函数去调用类A中的私有内容,需要提前在类A中将该成员函数声明为友元。

#include <iostream>
using namespace std;

class House;		//先声明存在House这样一个类,因为BestFriend类中会调用到该类,而House类中也需要声明将BestFriend设置为友元

class BestFriend {
public:
	BestFriend();		//此处只能先写出声明,需要在House类后再实现,原因与visit函数类似

	void visit();	//让visit函数可以访问House中的私有内容
	/*
	注意!此处不能把函数内容写在此处,由于函数中使用到了House类中的私有内容,虽然上面提前声明了House类,但其私有内容还是不能获取,依然会报错提示未定义类型House::BedRoom不可访问,将该函数内容移动到House类后面就不会报错了,就当作顺便学习函数对外实现了吧哈哈
	 {
	cout << "visit函数正在访问:" << house->m_SittingRoom << endl;
	cout << "visit函数正在访问:" << house->m_BedRoom << endl;
	}
	*/
	void visit2();	//让visit2函数不可以访问House中的私有内容

	House* house;
};

class House {
	//告诉编译器,BestFriend类中的visit成员函数是House类的友元,可以访问私有内容
	friend void BestFriend::visit();

public:
	House()
	{
		m_SittingRoom = "客厅";
		m_BedRoom = "卧室";
	}
	string m_SittingRoom;

private:
	string m_BedRoom;		//私有成员,卧室
};

BestFriend::BestFriend()
{
	house = new House;		//生成一个House类的指针对象house
}

void BestFriend::visit()
{
	cout << "visit函数正在访问:" << house->m_SittingRoom << endl;
	cout << "visit函数正在访问:" << house->m_BedRoom << endl;
}

void BestFriend::visit2()
{
	cout << "visit2函数正在访问:" << house->m_SittingRoom << endl;
	//cout << "visit2函数正在访问:" << house->m_BedRoom << endl;	//该行不可实现,因为该visit2函数不是House类的友元
}

void test()
{
	BestFriend bf;
	bf.visit();
	bf.visit2();
}

int main()
{
	test();
	return 0;
}

其中,主要代码为:

friend void BestFriend::visit();

​ 在这里,设置BestFriend类中的visit成员函数是House类的友元,可以访问House类中的私有内容。

注意!

与全局函数做友元所不同的是,类成员函数做友元不能把函数内容直接写在本类中,由于函数中使用到了House类中的私有内容,虽然之前提前声明了House类,但其私有内容还是不能获取,依然会报错提示House类中的私有成员不可访问:
成员函数后声明
但是,如果将该函数内容移动到House类后面就不会报错了,就当作顺便学习函数对外实现了吧哈哈~

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

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

相关文章

HTML学习(一)

Web标准 主要包括&#xff1a;结构&#xff0c;外观&#xff0c;行为三个方面 HTML标签&#xff0c;把标签学会&#xff0c;这门语言就基本学会了 双标签的关系&#xff0c;并列关系和包含关系 每个标签起作用的位置 vscode自动生成的代码的解释 <!DOCTYPE>文档类型声…

【RabbitMQ教程】第八章 —— RabbitMQ - 幂等性、优先级、惰性

&#x1f4a7; 【 R a b b i t M Q 教程】第八章—— R a b b i t M Q − 幂等性、优先级、惰性 \color{#FF1493}{【RabbitMQ教程】第八章 —— RabbitMQ - 幂等性、优先级、惰性} 【RabbitMQ教程】第八章——RabbitMQ−幂等性、优先级、惰性&#x1f4a7; &#x1f…

chatgpt赋能python:Python调试技巧:如何使用断点运行程序

Python调试技巧&#xff1a;如何使用断点运行程序 在Python编程中&#xff0c;程序出现错误或需要调试时&#xff0c;我们需要一些工具来帮助我们定位问题和修复代码。其中之一就是使用断点来运行程序。接下来我们将讨论如何在Python中使用断点进行程序调试的相关技巧。 什么…

C++11核心特性---右值引用(代码+讲解)

右值引用C11 1.左值和右值2.左值引用3.右值引用4.右值引用的性能优化空间5.移动语义6.值类别7.将左值转化为右值8.万能引用和引用折叠9.完美转发10.针对局部变量和右值引用的隐士类型转换11.总结 今天看到谢丙堃老师的《现代C语言核心特性解析》一书中关于右值引用的介绍&#…

21.网络编程|Java学习笔记

文章目录 网络的相关概念ipv4地址分类网路通信协议TCP和UDP InetAdress类SocketTCP网络通信编程应用案例服务端客户端 netstat指令TCP网络通讯不为人知的秘密 UDP网络通信编程【了解】网络传输文件代码示例 网络的相关概念 网络通信 网络 ip地址 1. 概念:用于唯一标识网络…

【数据库原理与应用 - 第七章】数据库安全性和完整性控制

目录 一、数据库安全性控制 二、数据库完整性控制 三、课后习题 数据库的保护功能&#xff1a;数据库安全性、完整性、数据库恢复、并发控制 一、数据库安全性控制 数据库的安全性&#xff1a;保护数据库&#xff0c;以防止非授权用户非法存取造成的数据泄密、更改、破坏DBM…

Python开发中的常见问题和解决方法:如何解决常见的性能和bug问题

第一章&#xff1a;引言 在Python开发中&#xff0c;我们经常会遇到一些常见的问题&#xff0c;包括性能瓶颈和程序错误&#xff08;bug&#xff09;。这些问题可能会影响我们的应用程序的运行效率和稳定性。因此&#xff0c;了解这些问题的根源并学习解决方法是非常重要的。本…

IDEA集成GitHub - Gitee集成

GitHub 集成 实际的开发中&#xff0c;代码都是采用IDE进行开发&#xff0c;所以我们这里介绍一下IDEA软件是如何集成GitHub远程仓库进行代码版本控制的。这里采用的IDEA版本为2022.2.1,其他版本的IDEA软件会略有差别。 1、 配置 Git 软件 2、 配置 GitHub 账号 继续点授权按…

三.数据类型

目录 1、布尔类型 2、整数类型 3、浮点数类型 4、字符类型 5、字符串类型 6、类型转换 1、布尔类型 Go语言中的布尔类型与其他语言基本一致&#xff0c;关键字也为bool&#xff0c;可赋值为预定义的true和false 示例代码如下&#xff1a; var v1 bool v1 true v2 :…

【TCP/IP】利用I/O复用技术实现并发服务器 - select函数

目录 I/O复用技术 select函数 设置文件描述符 指定监视范围 设置超时 I/O复用服务器端的实现 由服务器创建多个进程来实现并发的做法有时会带来一些问题&#xff0c;比如&#xff1a;内存上的开销、CPU的大量占用等&#xff0c;这些因素会消耗掉服务器端有限的计算资源、…

chatgpt赋能python:Python中如何更新pip版本

Python中如何更新pip版本 Python是一种非常强大的编程语言&#xff0c;它在现代编程领域中广泛使用。使用Python的好处之一是能够轻松地在其上安装和使用各种库&#xff0c;其中许多库由Python包管理器pip&#xff08;pip-installs-packages&#xff09;提供。尽管pip可以使Py…

新建的springboot 项目往往删除(1).mvn(2) .gitignore(3) HELP.md (4)mvnw (5)mvnw.cmd 文件

问题 新建的springboot 项目&#xff0c;项目开发人员往往删除&#xff08;1&#xff09;.mvn&#xff08;2&#xff09; .gitignore&#xff08;3&#xff09; HELP.md &#xff08;4&#xff09;mvnw &#xff08;5&#xff09;mvnw.cmd 文件&#xff0c;这些文件是什么&…

康耐视3D相机-DSMAX-VisionPro软件安装向导

机器视觉Halcon-字符识别 一. 系统需求 PC最小需求. OS: Win7 Pro/8Pro/10Pro X64 . Memory: 4GB RAM . PCIe 槽:X4 Gen2 一个 . 显存大小大于1GB 注意:1)PCIe插槽推荐使用x4 Gen 3; 软件版本VisionPro 9.2 CR1 X64/VisionPro 9.5及以上版本+ VisionPro_9_2_CR1_64-bit_…

合宙Air724UG Cat.1模块硬件设计指南--开关机

开关机 简介 模块支持上电后的开机、关机、复位三种状态&#xff0c;本章节会对其进行相应的介绍。 特性 PWRKEY&#xff1a; VILmin0V&#xff0c;VILmax0.5V&#xff0c;推荐值0.1V以下&#xff1b; 引脚状态&#xff1a;模块供电后PWRKEY内部拉高&#xff0c;满足低电平输入…

【哈佛积极心理学笔记】第22讲 自尊与自我实现

第22讲 自尊与自我实现 Unconditional self-esteem is the highest level, the level that Maslow would talk about “the self-actualization”, what David Schnarch talks about as “differentiated” or at the level of being known rather than desiring to be valida…

chatgpt赋能python:Python怎样使用断言?

Python怎样使用断言&#xff1f; 在Python中&#xff0c;断言是一种在程序执行中自动检查程序是否具有给定条件的方法。在程序的开发和调试过程中&#xff0c;通过正确使用断言&#xff0c;可以增强代码的可靠性并提升编程效率。 Python中的断言语法 Python中的断言语法非常…

CRC校验(2):CRC32查表法详解、代码实现及CRC反转

对于现在的CPU来说&#xff0c;基本上都在硬件上实现了CRC校验。但我们还是想用软件来实现一下CRC的代码&#xff0c;这样可以更深入地理解里面的原理。所以这一节就来详细地解释如何使用查表法从软件上来实现CRC-32的校验。另外&#xff0c;CRC还有一种反转的情况&#xff0c;…

MongoDB入门笔记

MongoDB入门笔记 1.MongoDB简介 MongoDB是一个开源、高性能、无模式的文档型数据库&#xff0c;当初的设计就是用于简化开发和方便扩展&#xff0c;是NoSQL数据库产品中的一种。是最像关系型数据库&#xff08;MySQL&#xff09;的非关系型数据库。 它支持的数据结构非常松散…

LuatOS-Air AT应用指南--CMUX

目录 简介 语法规则 参数定义 简介 CMUX是指串口多路复用。串口的多路复用器模式&#xff0c;就是使一个串行接口能够将数据传输到四个不同的客户应用程序。 要在Linux下使用模块的CMUX功能&#xff0c;需要在内核中开启相应的支持&#xff0c;开启方法见下图 将Air724UG开…

flink学习文档四 checkpoint机制

目的 checkpoint作为flink保障任务稳健运行的一个重要机制&#xff0c;在日常使用和flink 学习框架图 简单创建一个FlinkKafkaConsumer kafka是大数据中常用的消息存储中间件&#xff0c;也是flink任务中最常用的source源之一&#xff0c;因此flink 也为 kafka提供了内置的连接…