C++ 友元函数和友元类

news2024/10/7 4:26:16

前言

        在本文中,您将学习在C ++中创建友元函数和友元类,并在程序中有效地使用它们。OOP的重要概念之一是数据隐藏,即非成员函数无法访问对象的私有或受保护的数据。但是,有时这种限制可能迫使程序员编写冗长而复杂的代码。因此,C ++编程内置了一种机制,可以从非成员函数访问私有或受保护的数据,这是使用友元函数和友元类完成的。

C ++中的友元函数

        如果将函数定义为友元函数,则可以使用函数访问类的私有数据和受保护数据。通过使用关键字friend,编译器知道给定的函数是友元函数。要访问数据,应该在类的内部以关键字friend开始声明友元函数(可以是类内部的任何地方,可以是private部分,也可以是public部分)。

C ++中的友元函数声明

class class_name
{
    ... .. ...
    friend return_type function_name(argument/s);
    ... .. ...
}

现在,您可以将友元函数定义为访问该类数据的普通函数。friend定义中未使用任何关键字。

class className
{
    ... .. ...
    friend return_type functionName(argument/s);
    ... .. ...
}

return_type functionName(argument/s)
{
    ... .. ...
    // 可以从这个位置访问className的私有和受保护数据
     //因为此函数是className的友元函数。
    ... .. ...
}

 

/* C ++程序演示友元函数的工作。*/
#include<iostream>
class base {
public:
	
	// 友元函数
	friend int display_friend(base);
private:
	int a = 1;
protected:
	int b = 2;
};

// 友元函数的定义
int display_friend(base m) {
	//从非成员函数访问私有数据和受保护数据
	int c = m.a + m.b;
	return c;
}

int main() {
	base base1;
	std::cout << "输出:" << display_friend(base1) << std::endl;
	system("pause");
	return 0;
}

输出结果:

3

分析:

        这里,友元函数display_friend() 在base类中声明。因此,可以从这个函数访问类中的私有数据和受保护数据。

若将友元函数在类中的声明去掉,则程序会报错:
去掉友元函数在类中的声明之后代码如下:

/* C ++程序演示友元函数的工作。*/
#include<iostream>
class base {
public:
	
	// 友元函数
	//friend int display_friend(base);
private:
	int a = 1;
protected:
	int b = 2;
};

// 友元函数的定义
int display_friend(base m) {
	//从非成员函数访问私有数据和受保护数据
	int c = m.a + m.b;
	return c;
}

int main() {
	base base1;
	std::cout << "输出:" << display_friend(base1) << std::endl;
	system("pause");
	return 0;
}

编译器报错: 

使用友元函数添加两个不同类的私有或受保护成员变量

#include<iostream>
class base2; // 类base2的前置声明

class base1 {
public:
	
	// 友元函数声明
	friend int display_friend(base1, base2);
private:
	int a = 1;
};

class base2 {
public:
	// 友元函数声明
	friend int display_friend(base1, base2);

protected:
	int b = 2;
};

// 友元函数的定义
// 函数display_friend()是类base1和base2的友元函数
int display_friend(base1 m1, base2 m2) {
	//从非成员函数访问私有数据和受保护数据
	int c = m1.a + m2.b;
	return c;
}

int main() {
	base1 A;
	base2 B;
	std::cout << "输出:" << display_friend(A, B) << std::endl;
	system("pause");
	return 0;
}

 输出结果:

3

分析:

        在这个程序中,类base1和base2已经将display_friend()声明为friend函数。因此,这个函数可以访问这两个类的私有数据或受保护数据。在这里,display_friend()函数将两个对象A和B的私有数据 a 和受保护数据 b 相加,并将其返回给main函数。

        为了使这个程序正常工作,应该像上面的实例中所示的那样,对一个类base2进行前置声明。这是因为使用以下代码在class base1中引用了class base2的友元函数:friend int display_friend(base1,base2);

友元类(friend class)

        类似地,像一个友元函数一样,一个类也可以使用关键字friend成为另一个类的友元类。例如:

... .. ...
class B;
class A
{
   // class B 是 class A的友元类
   friend class B;
   ... .. ...
}

class B
{
   ... .. ...
}

        当一个类成为另一个类的friend类(友元类)时,这就意味着这个类的所有成员函数都是另一个类的友元函数。

        在这个程序中,B类的所有成员函数都是A类的朋友函数,因此B类的任何成员函数都可以访问A类的私有和受保护的数据,但是A类的成员函数不能访问B类的数据。

例如下面的代码:

#include<iostream>
class B; // 前置声明

class A {
	 // class B 是class A的友元类
	friend class B;

private:
	int a = 1;
protected:
	int b = 2;
};

class B {

public:
	// 类B的成员函数
	int displayB(A a1) {
		int c = a1.a + a1.b;
		return c;
	}
};

int main() {
	A a2;
	B b2;
	std::cout << b2.displayB(a2) << std::endl;
}

输出结果:

3

分析: 

        类B 为类A 的友元类,类B中的成员函数可以访问类A的私有数据和受保护数据。

C ++编程中如何互为友元类

        如何实现classA与B互为友元,即A可以访问B的私有,B也可以访问A的私有呢?案例如下:

#include<iostream>
class B; // 前置声明

class A {
	 // class B 是class A的友元类
	friend class B;

private:
	int a = 1;
protected:
	int b = 2;
public:
	int displayA(B);
};

class B {
	// class A 是class B 的友元类
	friend class A;

public:
	// 类B的成员函数
	int displayB(A a1) {
		int c = a1.a + a1.b;
		return c;
	}
private:
	int e = 3;
protected:
	int f = 4;
};


// 类A的成员函数
int A::displayA(B b1) {
	int g = b1.e + b1.f;
	return g;
}

int main() {
	A a2;
	B b2;
	std::cout << b2.displayB(a2) << std::endl; // 3
	std::cout << a2.displayA(b2) << std::endl; // 7
}

输出结果:
3
7

互为友元类的做法就是,在class A中声明friend class B;在classB 中声明friend class A;

注意:类A中使用到了类B的地方必须在类B的声明后定义,在类A中只能声明。例如上边类A中的displayA() 函数,不能在类A中直接定义,只能放在类B的声明之后定义。

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

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

相关文章

反向传播back propagation

深度学习概述 决定要怎么连接这些neuron的时候 就已经确定了function set 相比于之前做logistic regression&#xff0c;linear regression的时候&#xff0c;换一个方式来决定function set 比较大&#xff0c;包含了logistic regression&#xff0c;linear regression没法包含…

【C++入门 一 】学习C++背景、开启C++奇妙之旅

目录 1.什么是C2. C的发展史3. C的重要性3.1 语言的使用广泛度3.2 在工作领域1. 操作系统以及大型系统软件开发2. 服务器端开发3. 游戏开发4. 嵌入式和物联网领域5. 数字图像处理6. 人工智能7. 分布式应用 3.3 在校招领域3.3.1 岗位需求3.3.2 笔试题 4. 如何学习C4.1 别人怎么学…

工业电子中的深力科分享一款PWM控制器 KA3525A

关于PWM控制器&#xff1a; PWM控制器是一种用于控制电机或其他设备的电路&#xff0c;它通过改变脉冲宽度调制&#xff08;PWM&#xff09;信号的占空比来控制设备的输出。PWM控制器可以使用单片机或开发板等设备来实现&#xff0c;通过设定占空比&#xff0c;可以轻松地控制…

LeetCode —— dfs和bfs

797. 所有可能的路径 给你一个有 n 个节点的 有向无环图&#xff08;DAG&#xff09;&#xff0c;请你找出所有从节点 0 到节点 n-1 的路径并输出&#xff08;不要求按特定顺序&#xff09;。 graph[i] 是一个从节点 i 可以访问的所有节点的列表&#xff08;即从节点 i 到节点…

【斗罗二】天梦哥告白冰帝,唐三再返场,雨浩通过冰帝考验,觉醒新武魂

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析斗罗大陆2绝世唐门国漫资讯。 斗罗大陆动画第二部绝世唐门第19集已经更新了&#xff0c;全都是霍雨浩与天梦哥在极北之地&#xff0c;吸引冰帝加入造神计划的过程。不仅有天梦哥的爱情宣言告白&#xff0c;唐三也再次限时…

设计模式_备忘录模式

备忘录模式 介绍 设计模式定义案例问题堆积在哪里解决办法备忘录模式行为型模式&#xff0c; 保存了数据某一个时间点的状态 在需要的时候进行回档单机游戏的角色 数据保存并且回档保存和回档加一个状态管理类 类图 代码 MomentData using UnityEngine;public class MomentD…

SLAM从入门到精通(从仿真到实践)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 之前花了40多篇文章&#xff0c;弄清了什么是slam&#xff0c;怎么学习slam&#xff0c;什么是ros&#xff0c;怎么利用ros来学好slam等等。不仅如…

云安全(1)--初识容器逃逸之特权容器逃逸

文章目录 前言privileged,特权容器逃逸环境配置实际利用实际环境利用计划任务/var/spool/cron/crontabs/ 适用于ubuntu debain/var/spool/cron 适用于centos ld.so.preloadssh 前言 在10.15号的上海中华武数杯的渗透赛里做到了一个k8s的题目&#xff0c;这应该是我第一次在比赛…

13.3测试用例进阶

一.测试对象划分 1.界面测试(参考软件规格说明书和UI视觉稿) a.什么是界面 1)WEB站(浏览器) 2)app 3)小程序 4)公众号 b.测试内容 1)界面内容显示的一致性,完整性,准确性,友好性.比如界面内容对屏幕大小的自适应,换行,内容是否全部清晰展示. 2)验证整个界面布局和排版…

【数据结构】线性表(七)堆栈:链式栈及其基本操作(初始化、判空、入栈、出栈、存取栈顶元素、清空栈);顺序栈与链式栈之比较

文章目录 一、堆栈1. 定义2. 基本操作 二、顺序栈三、链式栈0. 链表1. 头文件和常量2. 栈结构体3. 栈的初始化4. 判断栈是否为空5. 入栈6. 出栈7. 存取栈顶元素8. 清空栈9. 主函数10. 代码整合 四、 顺序栈与链式栈的比较 堆栈&#xff08;Stack&#xff09;和队列&#xff08;…

Linux MMC子系统 - 1.eMMC简介

By: Ailson Jack Date: 2023.10.21 个人博客&#xff1a;http://www.only2fire.com/ 本文在我博客的地址是&#xff1a;http://www.only2fire.com/archives/160.html&#xff0c;排版更好&#xff0c;便于学习&#xff0c;也可以去我博客逛逛&#xff0c;兴许有你想要的内容呢。…

JAVA基础-数据类型(2)

目录 1、基本数据类型2、引用数据类型3、类型默认值4、数据类型的转换4.1、自动类型转换4.2、强制类型转换4.3、隐含强制类型转换 1、基本数据类型 :::tips Java语言提供了八种基本类型。六种数字类型&#xff08;四个整数型&#xff0c;两个浮点型&#xff09;&#xff0c;一…

C++多重、多层、分层继承

在本文中&#xff0c;您将学习C 编程中的不同继承模型&#xff1a;带有示例的多继承&#xff0c;多层和分层继承。 继承是面向对象编程语言的核心功能之一。它允许软件开发人员从现有的类派生一个新的类。派生类继承基类&#xff08;现有类&#xff09;的功能。C 编程中有多种…

逗号表达式

#include<stdio.h> int cmp() {return(2,1); } int main() {int z cmp();printf("%d",z);return 0; } 逗号表达式括号里的优先级是自左向右&#xff0c;最后一个值为最终的结果。

YOLOv5改进实战 | 更换主干网络Backbone(四)之轻量化模型MobileNetV3

前言 轻量化网络设计是一种针对移动设备等资源受限环境的深度学习模型设计方法。下面是一些常见的轻量化网络设计方法: 网络剪枝:移除神经网络中冗余的连接和参数,以达到模型压缩和加速的目的。分组卷积:将卷积操作分解为若干个较小的卷积操作,并将它们分别作用于输入的不…

东信智能:嵌入式内置式身份证阅读器微模块技术参数,和之前的大模块、小模块有什么区别研究

身份证读卡器模块总共分为4种&#xff1a; 1、0503大模块&#xff0c;尺寸大&#xff0c;可读完整信息。 2、0513小模块&#xff0c;尺寸中等&#xff0c;可读完整信息。 3、微模块&#xff0c;尺寸小&#xff0c;只用于比对。 4、SDT88-FR嵌入式模块&#xff0c;尺寸小&am…

“控制情绪,理性交流”刍议

今天&#xff0c;本“人民体验官”还是回避推广人民日报官方微博文化产品《走出低谷期的9个习惯》。 截图&#xff1a;来源“人民体验官”推广平台 ​之前&#xff0c;由于笔者读过《人民日报》曾经发表过的关于“学会管理情绪 ”的文章&#xff0c;对文章中这些观点深表认同&…

DJYOS物联屏:工业HMI里的显控异构计算的超稳定解决方案

1、超稳定性&#xff1a;DJYOS物联屏的超稳定依赖于都江堰泛计算操作系统天然支持多核、多机的异构计算能力&#xff0c;可以一核运行HMI、一核运行控制程序&#xff0c;多核之间可以通过djyos的异构计算去中心化运行&#xff08;确保各自程序不干扰运行&#xff09;&#xff0…

存储器~Zynq book第九章

还有小梅哥和正点原子的一些资料。 DRAM SRAM Cache SDRAM SDRAM学习与实现串口传图-CSDN博客 DDR3

【算法训练-动态规划 零】动态规划解题框架

动态规划问题的一般形式就是求最值。动态规划其实是运筹学的一种最优化方法&#xff0c;只不过在计算机问题上应用比较多&#xff0c;比如说求最长递增子序列呀&#xff0c;最小编辑距离呀等等。 既然是要求最值&#xff0c;核心问题是什么呢&#xff1f;求解动态规划的核心问…