[C++ 从入门到精通] 15.友元函数、友元类、友元成员函数

2023-12-18 14:36

本文主要是介绍[C++ 从入门到精通] 15.友元函数、友元类、友元成员函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • 📢博客主页:https://loewen.blog.csdn.net
  • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
  • 📢本文由 丶布布原创,首发于 CSDN,转载注明出处🙉
  • 📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨

文章预览:

      • 一. 前言
      • 二. 友元函数
      • 三. 友元类
      • 四. 友元成员函数


一. 前言

众所周知,C++控制对类对象私有成员的访问。通常,公有类方法(public)提供唯一的访问途径,但是有时候这种限制太严格,以至于不适合特定的编程问题。

在这种情况下,C++提供了另外一种形式的访问权限:友元,友元有3种:

  • 友元函数;
  • 友元类;
  • 友元成员函数;

优缺点

  • 优点:通过让函数成为类的友元(即:友元函数),可以赋予该函数与类的成员函数相同的访问权限,使其可以访问本类protected、private成员,在某些频繁访问成员变量的地方可以提高性能。

  • 缺点:友元破坏了面向对象的封装性。


二. 友元函数

1、通过friend将一个函数(友元函数是个函数)声明为某个类的友元函数,那么该函数就能访问这个类的所有成员(成员变量、成员函数),无论是public,private,protected

2、因为友元函数不属于类成员,所以其不受public/protected/private的限制,放在public/protected/private下声明都行。

代码展示

#include <iostream>
using namespace std;class A
{
private:int data;void display(){cout << "data = " << data << endl;}friend void change(int x, A& a); // 将函数change()声明为类A的友元函数
};void change(int x, A& a)
{a.data = x;a.display();
}int main()
{A a;change(10, a);return 0;
}

三. 友元类

1、可以在类A中把类B声明为类A的友元类,此时,在类B(类A的友元类)的成员函数中,可以访问类A的所有成员(成员变量、成员函数),无论是public,private,protected

2、由于友元类不属于类成员,所以友元类的声明不受public、protected、private的影响。

代码展示Tip:为什么需要类B的声明):

#include <iostream>
using namespace std;class B; // 类B的声明,类A用到了类B,而类B的定义有可能在类A的定义之后导致编译出错,所以最好先声明一下类B
class A
{
private:int data;void display(){cout << "data = " << data << endl;}friend class B; // 将类B声明为类A的友元类(用到了类B的名字,所以需要前面声明一下class B; )
};class B
{
public:void change(int x, A& a){a.data = x;  //在类B(类A的友元类)的成员函数中,可以访问类A的所有成员(成员变量、成员函数),无论是public,private,protecteda.display();}
};int main()
{A a;B b;b.change(50, a);return 0;
}

注意:每个类都负责控制自己的友元类和友元函数:

  • 友元关系不能被继承
  • 友元关系是单向的,比如类B是类A的友元类,但这并不代表类A是类B的友元类;
  • 友元关系没有传递性,比如类B是类A的友元类,类C是类B的友元类,但这并不代表类C是类A的友元类;

四. 友元成员函数

友元成员函数:即是本类的成员函数,又是其他类的友元函数。

代码展示

A.h(Tip:为什么使用#include "B.h"而不用class B;声明类B

#ifndef __A_H
#define __A_H#include <iostream>//class B;   //注:声明友元成员函数不能仅仅使用类B的声明了,因为在friend void B::change(int x, A& a)不仅仅用到了类B的名字,//还用到了其成员函数change(),系统需要先判断类B中是否有其成员函数change(),所以需要用#include "B.h"
#include "B.h"class A
{
private:int data;void display(){std::cout << "data = " << data << std::endl;}friend void B::change(int x, A& a); // 该函数是友元成员函数的声明:将类B的成员函数change()声明为类A的友元函数
};#endif

B.h

#ifndef __B_H
#define __B_Hclass A; // 类A的声明class B
{
public:void change(int x, A& a); // 只有public的成员函数才能成为其它类的友元函数
};#endif

B.cpp

#include "A.h"
#include "B.h"void B::change(int x, A& a)
{a.data = x;a.display();
}

main.cpp

#include "A.h"
#include "B.h"int main()
{A a;B b;b.change(50, a);return 0;
}

下雨天,最惬意的事莫过于躺在床上静静听雨,雨中入眠,连梦里也长出青苔。

这篇关于[C++ 从入门到精通] 15.友元函数、友元类、友元成员函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/508764

相关文章

MySQL 中的 CAST 函数详解及常见用法

《MySQL中的CAST函数详解及常见用法》CAST函数是MySQL中用于数据类型转换的重要函数,它允许你将一个值从一种数据类型转换为另一种数据类型,本文给大家介绍MySQL中的CAST... 目录mysql 中的 CAST 函数详解一、基本语法二、支持的数据类型三、常见用法示例1. 字符串转数字2. 数字

Python内置函数之classmethod函数使用详解

《Python内置函数之classmethod函数使用详解》:本文主要介绍Python内置函数之classmethod函数使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 类方法定义与基本语法2. 类方法 vs 实例方法 vs 静态方法3. 核心特性与用法(1编程客

从入门到精通MySQL联合查询

《从入门到精通MySQL联合查询》:本文主要介绍从入门到精通MySQL联合查询,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下... 目录摘要1. 多表联合查询时mysql内部原理2. 内连接3. 外连接4. 自连接5. 子查询6. 合并查询7. 插入查询结果摘要前面我们学习了数据库设计时要满

Python函数作用域示例详解

《Python函数作用域示例详解》本文介绍了Python中的LEGB作用域规则,详细解析了变量查找的四个层级,通过具体代码示例,展示了各层级的变量访问规则和特性,对python函数作用域相关知识感兴趣... 目录一、LEGB 规则二、作用域实例2.1 局部作用域(Local)2.2 闭包作用域(Enclos

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

MySQL count()聚合函数详解

《MySQLcount()聚合函数详解》MySQL中的COUNT()函数,它是SQL中最常用的聚合函数之一,用于计算表中符合特定条件的行数,本文给大家介绍MySQLcount()聚合函数,感兴趣的朋... 目录核心功能语法形式重要特性与行为如何选择使用哪种形式?总结深入剖析一下 mysql 中的 COUNT

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

MySQL 中 ROW_NUMBER() 函数最佳实践

《MySQL中ROW_NUMBER()函数最佳实践》MySQL中ROW_NUMBER()函数,作为窗口函数为每行分配唯一连续序号,区别于RANK()和DENSE_RANK(),特别适合分页、去重... 目录mysql 中 ROW_NUMBER() 函数详解一、基础语法二、核心特点三、典型应用场景1. 数据分

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方