C++:友元

内容提要

  • 面向对象

    • 友元

友元

生活中的你家有客厅(public),有卧室(private)

客厅所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你自己可以进入。

但是呢,你也可以允许客人中你的朋友进去。

在程序里,有些私有成员,也想让类外特殊的一些函数或者类进行访问,就需要用到友元

友元的目的是让一个函数或者类访问另一个类中的私有成员。

友元的关键字为friend

友元的三种实现:

①全局函数做友元

②类做友元

③成员函数做友元

全局函数做友元

复制代码
 /*************************************************************************
   > File Name:    demo01.cpp
   > Author:       柯柯大王
   > Description:  友元:全局函数做友元
   > Created Time: 2025-08-21 08:52:42
  ************************************************************************/
 #include <iostream>
 #include <string>
 #include <iomanip>
 ​
 using namespace std;
 ​
 //创建Building类
 class Building
 {
     //告诉编译器 goodFriend全局函数 是Building类的好朋友,可以访问类中的私有成员
     friend void goodFriend(Building* building); //friend 函数
 public:
     //无参构造,此时会覆盖掉默认的无参
     Building()
     {
         //赋值
         this->sittingRoom = "客厅";
         this->bedRoom = "卧室";
     }
 public:
     string sittingRoom;    //客厅  公共成员
 private:
     string bedRoom;        //卧室  私有成员
 };
 ​
 //准备一个全局函数,用来做友元,实现对类中私有成员 bedRoom的访问
 void goodFriend(Building* building)
 {
     cout << "好朋友正在造访:" << building->sittingRoom << endl;   //客厅,正常访问
     cout << "好朋友正在造访:" << building->bedRoom << endl;       //卧室,需要借助友元访问
 }
 ​
 int main(int argc, char **argv)
 {
     Building b;
     goodFriend(&b);
     
     system("pause");
     return 0;
 }

类做友元

复制代码
 /*************************************************************************
   > File Name:    demo02.cpp
   > Author:       柯柯大王
   > Description:  友元:类做友元
   > Created Time: 2025-08-21 09:58:18
  ************************************************************************/
 #include <iostream>
 #include <string>
 #include <iomanip>
 ​
 using namespace std;
 ​
 //创建类BUilding
 class Building
 {
     //告诉编译器 GoodFriend类是Building类的好朋友,可以访问到Building类中的私有成员
     friend class GoodFriend;
 public:
     Building();
     string sittingRoom;   //客厅  公共成员
 private:
     string bedRoom;        //卧室  私有成员
 };
 ​
 //定义Building类的构造函数
 Building::Building()
 {
     this->sittingRoom = "客厅";
     this->bedRoom = "卧室";
 }
 ​
 //创建类GoodFriend
 class GoodFriend
 {
 public:
     GoodFriend()
     {
         this->building = new Building(); //此时就不在栈区,在 自由存储区,大概率在堆区
     }
     
     //访问好朋友(友元)Building的私有成员
     void visit()
     {
         cout << "好朋友正在造访:" << building->sittingRoom << endl;   //客厅,正常访问
         cout << "好朋友正在造访:" << building->bedRoom << endl;       //卧室
     }
 private:
     Building *building; 
 };
 ​
 //void GoodFriend::visit()
 //{
 //  cout << "好朋友正在造访:" << building->sittingRoom << endl;   //客厅,正常访问
 //  cout << "好朋友正在造访:" << building->bedRoom << endl;       //卧室 
 //}
 ​
 int main(int argc, char **argv)
 {
     GoodFriend gf;
     gf.visit();
     
     system("pause");
     return 0;
 }

成员函数做友元

复制代码
 #include <iostream>
 #include <string>
 #include <iomanip>
 using namespace std;
 // 类的声明,主要是解决类的嵌套
 class Building;
 // 类的定义
 // 创建友元类
 class GoodFriend
 {
 public:
  GoodFriend();
  
  void visit();
 private:
  Building *building; 
 };
 // 创建Building类
 class Building
 {
  // 告诉编译器 GoodFrind类中某个函数(visit)作为Building类的好朋友,可以
 访问Building中的私有成员
  friend void GoodFriend::visit();
 public:
  // 无参构造函数
  Building()
  {
  // 初始化(所谓初始化,就是给类对象的成员变量赋初值)
  this->sittingRoom = "客厅";
  this->bedRoom = "卧室";
  }
 public:
  string sittingRoom;    // 客厅 公共成员
 private:
  string bedRoom;        // 卧室 私有成员
  
 };
 GoodFriend::GoodFriend()
 {
  this->building = new Building();
 }
 void GoodFriend::visit()
 {
  cout << "好朋友正在造访:" << building->sittingRoom << endl;  // 客
 厅,正常访问
  cout << "好朋友正在造访:" << building->bedRoom << endl;      // 卧
 室,需要借助友元访问
 }
 int main(int argc, char **argv)
 {
  GoodFriend gf;
  gf.visit();
  
  system("pause");
  return 0;
 }    

如果涉及到类的嵌套访问,比如成员函数做友元的时候。我们建议将成员函数定义到类的外部,同时需要给类加上类声明。

运算符重载【了解】

运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以使用不同的数据类型。

加号运算符

**作用:**实现两个自定义数据类型相加的运算

示例:

复制代码
 #include <iostream>
 #include <string>
 #include <iomanip>
 using namespace std;
 class Person
 {
 public:
  Person(){}
  Person(int a, int b)
  {
  this->a = a;
  this->b = b;
  }
  
  // 成员函数实现 + 号运算符重载
 Person operator+(const Person& p)
  {
  Person temp;
  temp.a = this->a + p.a;
  temp.b = this->b + p.b;
  return temp;
  }
 public:
  int a;
  int b;
 };
 // 全局函数实现 + 号运算符重载
 Person operator+(const Person& p1, const Person& p2)
 {
  Person temp;
  temp.a =p1.a + p2.a;
  temp.b =p1.b + p2.b;
  return temp;
 }
 // 运算符重载 可以发生函数重载
 Person operator+(const Person& p2, int val)
 {
  Person temp;
  temp.a =p2.a + val;
  temp.b =p2.b + val;
  return temp;
 }
 int main(int argc, char **argv)
 {
  Person p1(10,20);
  Person p2(20,20);
  
  // 测试成员函数方式
  Person p3 = p2 + p1;  // 相当于 p3 = p2.operator+(p1)
  cout << "a = " << p3.a << ",b = " << p3.b  << endl;
  
  Person p4 = p3 + 10;  // 相当于 p4 = operator+(p3, 10)
  cout << "a = " << p4.a << ",b = " << p4.b  << endl;
  system("pause");
  return 0;
 }
 ​

总结1:对于内置的数据类型的表达式的运算符是不可能改变的
总结2:不要滥用运算符重载

相关推荐
x70x8014 小时前
C++中不同容器的用法及接口(vector / deque / stack / queue / priority_queue)
开发语言·c++
再__努力1点14 小时前
LBP纹理特征提取:高鲁棒性的纹理特征算法
开发语言·人工智能·python·算法·计算机视觉
lsx20240614 小时前
Bootstrap4 卡片布局指南
开发语言
ZPC821014 小时前
PPO算法训练机器人时,如何定义状态/动作/奖励
人工智能·算法·机器人
superman超哥14 小时前
仓颉热点代码识别深度解析
开发语言·后端·python·c#·仓颉
永远都不秃头的程序员(互关)14 小时前
数据结构实战:从复杂度到C++实现
算法
是一个Bug14 小时前
Java主流框架面试题(一)
java·开发语言
努力学算法的蒟蒻15 小时前
day42(12.23)——leetcode面试经典150
算法·leetcode·面试
百***074515 小时前
Step-Audio-2 API 中转调用解决方案:2025 年版
开发语言·php
情爱少有真诚15 小时前
Java集合框架:数据存储与操作的利器
java·开发语言·经验分享·课程设计·ai编程