【C++】友元–最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

【C++】友元–最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)本文详细介绍了 C 编程中的友元函数 包括其概念 分类 全局函数 成员函数和类 应用场景 如操作符重载 以及友元的注意事项和优缺点 帮助理解如何在设计中灵活运用友元以提高代码灵活性和效率

大家好,欢迎来到IT知识分享网。

目录

一、前言

 二、友元是什么?

 三、友元的感性理解和分类

🥝友元的感性理解 

🍋友元的三种分类

✨友元 — 全局函数

✨友元 — 成员函数

✨友元 — 类

 四、友元函数的应用场景 

🍍操作符重载 :”<<”  与  “>>”

五、友元的注意事项

🍋 友元函数的注意事项

🍇 友元类的注意事项

 六、友元的优缺点

🍓友元 — 优点

🍉友元 — 缺点

七、共勉 


一、前言

       C++编程语言中,友元函数(Friend Function)是一种特殊的函数,具有访问类中私有成员和保护成员的权限,尽管它不是类的成员函数。友元函数的存在使得类的设计更加灵活,能够在需要时授予外部函数访问类的私有成员的能力。本文将详细介绍C++中的友元函数,包括其定义、使用场景、优缺点以及示例

 二、友元是什么?

       1️⃣: 友元是在一个类中声明的一个非成员函数,但在类的内部声明该函数为友元。这意味着该函数可以访问该类的私有成员,包括私有变量和私有函数
      2️⃣: 友元的声明通常位于类的声明中,但其实现则位于类外部。 

 三、友元的感性理解和分类

🥝友元的感性理解 

    上述对友元的描述可能比较抽象,大家难以理解,我们可以通过一个生活小案例来感性理解一下

  • 在我们的日常生活中,假设大家都住在别墅社区里面, 在每栋别墅里面都是房间的,像客厅、卧室、厨房、洗手间,每家每户基本都有,我们可以将这些私人的房屋称为你的 —- 私人区域

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

  • 那在一个小区中,除了挨家挨户的的私人领域外,一定会存在公共区域,在这些公共区域中,会有一些公共场所,例如像篮球场、咖啡馆、游泳馆、小卖部或是健身器材等等,我们可以将这些所有人都可以访问的地方称为 —–  公共区域

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

  • 所以 篮球场、健身区域就相当于 —- 公共区域,大家都可以来玩,你的家就相当于 —– 私人领域,只有你能进去。
  •  但是千防万防你都很难防住 —- 隔壁老王 —- 去你家

      所以在程序里,有些私有属性 也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术隔壁老王

  • 友元的目的:就是让一个函数或者类 访问另一个类中的私有成员
  • 友元的关键字friend 

 🍋友元的三种分类

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

 ✨友元 — 全局函数

 首先,我们要定义一个社区类公共成员变量为—-公共区域,私有成员变量为—家

// 创建一个社区的类 // 一个社区里面有大家可以一起活动的 公共区域 也有自己的私人空间 家 class Community { public: // community 的构造函数 ,给成员变量 赋 初始值 Community() { PublicAreas = "公共区域"; home = "家"; } string PublicAreas; // 公共区域 private: string home; // 家 };

然后定义一个全局函数 laoWang(),用来访问Community类中的私有成员

void laowang(Community& communtiy) { // 访问了私人区域 cout << "隔壁老王 全局函数 正在偷偷潜入 你家:(引用传递)" << communtiy.home << endl; // 访问了公有区域 cout << "隔壁老王 全局函数 正在公共区域 打球:(引用传递)" << communtiy.PublicAreas << endl; }

 此时我们来测试一个看是否可以成功

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

 此时就需要隔壁老王—-友元函数出手啦

 关键代码

friend void laowang(Community& communtiy);

在Community类中声明友元函数,告诉编译器 laoWang 全局函数是 Community类 的好朋友,可以访问Community对象的私有成员

// 创建一个社区的类 // 一个社区里面有大家可以一起活动的 公共区域 也有自己的私人空间 家 class Community { friend void laowang(Community& communtiy); public: // community 的构造函数 ,给成员变量 赋 初始值 Community() { PublicAreas = "公共区域"; home = "家"; } string PublicAreas; // 公共区域 private: string home; // 家 };

下面给出全局函数做友元访问类的私有成员的完整示例代码

// 全局函数做--- 友元 // 创建一个社区的类 // 一个社区里面有大家可以一起活动的 公共区域 也有自己的私人空间 家 class Community { friend void laowang(Community& communtiy); public: // community 的构造函数 ,给成员变量 赋 初始值 Community() { PublicAreas = "公共区域"; home = "家"; } string PublicAreas; // 公共区域 private: string home; // 家 }; void laowang(Community& communtiy) { // 访问了私人区域 cout << "隔壁老王 全局函数 正在偷偷潜入 你家:(引用传递)" << communtiy.home << endl; // 访问了公有区域 cout << "隔壁老王 全局函数 正在公共区域 打球:(引用传递)" << communtiy.PublicAreas << endl; } int main() { // 创建一个社区对象 Community community; laowang(community); return 0; }

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

✨友元 — 成员函数

 我们首先声明一个Community类,防止在下面的Laowang类中,编译器不认识Community

//前置类的声明 class Community; 

然后定义Laowang类,采用成员函数在类内声明,类外定义的方式

class Laowang { public: void visit(); private: }; void Laowang::visit() { Community _community; cout << "隔壁老王类正在访问:" << _community.PublicAreas << endl; cout << endl; cout << "隔壁老王类正在访问:" << _community.home << endl; }

下面给出Community类的定义 

class Community { public: // 构造函数 Community() { PublicAreas = "公共区域"; home = "你家"; } string PublicAreas; // 私有成员 private: string home; };

 同样的,现在还没有声明友元,因此类中的成员函数还不能访问另一个类的私有成员

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

 此时就需要隔壁老王—-友元函数出手啦

 关键代码 

friend void Laowang::visit();

在Community类中声明友元函数告诉编译器, Laowang 类中的 visit()函数 是Community类的好友,可以访问 Community类的私有区域(你家)

class Community { // 告诉编译器, Laowang 类中的 visit()函数 是Community类的好友,可以访问 Community类的私有区域(你家) friend void Laowang::visit(); public: // 构造函数 Community() { PublicAreas = "公共区域"; home = "你家"; } string PublicAreas; // 私有成员 private: string home; };

 下面给出成员函数做友元访问类的私有成员的完整示例代码

// 成员函数 做 友元 //前置类的声明 class Community; class Laowang { public: void visit(); private: }; class Community { // 告诉编译器, Laowang 类中的 visit()函数 是Community类的好友,可以访问 Community类的私有区域(你家) friend void Laowang::visit(); public: // 构造函数 Community() { PublicAreas = "公共区域"; home = "你家"; } string PublicAreas; // 私有成员 private: string home; }; void Laowang::visit() { Community _community; cout << "隔壁老王类正在访问:" << _community.PublicAreas << endl; cout << endl; cout << "隔壁老王类正在访问:" << _community.home << endl; } int main() { Laowang lw; lw.visit(); return 0; }

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

✨友元 — 类

 我们首先声明一个Laowang类,防止在下面的Community 类中,编译器不认识Laowang类 

// 前置类的声明 class Laowang;

 然后定义 Community 类

class Community { public: // 创建 构造函数 Community() { // 初始化赋值 PublicAreas = "公共区域"; home = "你家"; } string PublicAreas; // 公共区域 private: string home; // 家 };

 然后定义Laowang类,采用成员函数在类内声明,类内定义的方式。(采用成员函数在类内声明,类外定义也可以)

// 定义 一个老王类 class Laowang { public: // 构造函数 Laowang() {} // 参观函数,用于老王进入你家-----访问 Community中的属性 void visit() { cout << "隔壁老王类正在访问:" << _community.PublicAreas << endl; cout << endl; cout << "隔壁老王类正在访问:" << _community.home << endl; } private: //自定义类 Community _community; };

 同样的,现在还没有声明友元,因此类中的成员函数还不能访问另一个类的私有成员

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

 此时就需要隔壁老王—-友元函数出手啦

 关键代码

friend class Laowang;

 在Community类中声明友元函数告诉编译器, Laowang类是Community类的好朋友,可以访问Community类的私有成员(你家)

class Community { // 告诉编译器,Laowang类是Community类的好朋友,可以访问Community类的私有成员(你家) friend class Laowang; public: // 创建 构造函数 Community() { // 初始化赋值 PublicAreas = "公共区域"; home = "你家"; } string PublicAreas; // 公共区域 private: string home; // 家 };

下面给出 类 做友元访问类的私有成员的完整示例代码

// 类 做 友元 // 前置类的声明 class Laowang; class Community { // 告诉编译器,Laowang类是Community类的好朋友,可以访问Community类的私有成员(你家) friend class Laowang; public: // 创建 构造函数 Community() { // 初始化赋值 PublicAreas = "公共区域"; home = "你家"; } string PublicAreas; // 公共区域 private: string home; // 家 }; // 定义 一个老王类 class Laowang { public: // 构造函数 Laowang() {} // 参观函数,用于老王进入你家-----访问 Community中的属性 void visit() { cout << "隔壁老王类正在访问:" << _community.PublicAreas << endl; cout << endl; cout << "隔壁老王类正在访问:" << _community.home << endl; } private: //自定义类 Community _community; }; int main() { // 创建一个 老王 的对象 Laowang lw; lw.visit(); return 0; }

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

 四、友元函数的应用场景 

🍍操作符重载 :”<<”  与  “>>”

当需要重载类的操作符(如<<、>>、+、-等)时,友元函数可以访问私有成员,实现合适的操作。 

接下来,就写个自定义类型的<< 和 >>的重载来演示友元函数:

  • >> 流提取
  • << 流插入

C++里cout和cin是全局的对象包含在<iostream>的,cinistream类型对象coutostream类型 对象 

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

C++中,内置类型是直接支持cout流插入<<和cin流提取>>的,并且其可以自动识别类型。其原因是库里面已经把这些内置类型的给重载了: 

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

 而自定义类型就不能直接用>>或<<,因此,我们需要手写这两个的运算符重载。

❓问题:现在我们尝试去重载 operator<< ,然后发现我们没办法将 operator<< 重载成成员函数。因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。this 指针默认是第一个参数也就是左操作数了。但是实际使用中 cout 需要是第一个形参对象,才能正常使用。所以我们要将 operator<< 重载成全局函数。但是这样的话,又会导致类外没办法访问成员,那么这里就需要友元来解决。operator>>同理。

  •  我们拿 — 日期类 — 来举例说明
// 输出输入 流 << >> class Date { //友元函数 friend ostream& operator<<(ostream& out, const Date& d);//流插入 << friend istream& operator>>(istream& in, Date& d);//流提取 >> public: Date(int year = 1, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } private: int _year; int _month; int _day; }; //流插入 <<.. ostream& operator<<(ostream& out, const Date& d) { out << d._year << "-" << d._month << "-" << d._day << endl; return out; } //流提取 >> istream& operator>>(istream& in, Date& d) { in >> d._year >> d._month >> d._day; return in; } int main() { Date d1; cin >> d1; cout << endl; cout << "输出今天的日期:"<<d1; }

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

五、友元的注意事项

🍋 友元函数的注意事项

1️⃣:友元函数可访问类的私有和保护成员,但不是类的成员函数

2️⃣:友元函数不能用const修饰

  •         因为友元函数只是一个全局函数,不属于类的成员函数,所以它没有隐藏的this指针,而const修饰的就是this指针,只有非静态的成员函数才能用const修饰

3️⃣:友元函数可以在类定义的任何地方声明,不受类访问限定符限制
4️⃣:一个函数可以是多个类的友元函数

  • 比如说一个函数需要访问多个类中的私有成员,那可以在那几个类中设置这个函数为他们的友元函数,这样就都可以访问了

🍇 友元类的注意事项

1️⃣:友元关系是单向的,不具有交换性

  • 比如上述Community类和Laowang类,在Community类中声明Laowang类为其友元类,那么可以在Laowang类中直接访问Community类的私有成员变量,但想在Community类中访问Laowang类中私有的成员变量则不行。

2️⃣:友元关系不能传递

  • 如果B是A的友元,C是B的友元,则不能说明C时A的友元。

 六、友元的优缺点

 🍓友元 — 优点

1、访问私有成员:
主要作用是允许外部函数或类访问另一个类的私有成员,从而实现对类的细粒度控制。
2、操作符重载:
当需要重载类的操作符(如<<、>>、+、-等)时,友元函数可以访问私有成员,实现合适的操作。
3、提高效率:
在某些情况下,使用友元函数可以提高程序的执行效率,因为它可以直接访问类的私有成员,而不需要通过访问器函数(getter和setter)。




🍉友元 — 缺点

 1、破坏封装性:
友元函数可以突破类的封装性,使得类的私有成员可以被外部函数直接访问,可能会降低代码的安全性和可维护性。(友元也破环了类的隐藏与封装,所以必须慎用 (牺牲安全,提高效率))
2、难以维护:
当程序变得复杂时,友元函数的使用可能会导致代码变得难以理解和维护。


3、友元不能 继承,交换,传递

七、共勉 

     以下就是我对 友元–最全解析 的理解,如果有不懂和发现问题的小伙伴,请在评论区说出来哦,同时我还会继续更新对 C++ 的理解,请持续关注我哦!!!   

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/117113.html

(0)
上一篇 2025-11-23 17:45
下一篇 2025-11-23 18:10

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信