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:不要滥用运算符重载

相关推荐
haoly19893 小时前
数据结构和算法篇-归并排序的两个视角-迭代和递归
数据结构·算法·归并排序
微笑尅乐3 小时前
中点为根——力扣108.讲有序数组转换为二叉搜索树
算法·leetcode·职场和发展
小梁努力敲代码3 小时前
java数据结构--List的介绍
java·开发语言·数据结构
云知谷4 小时前
【HTML】网络数据是如何渲染成HTML网页页面显示的
开发语言·网络·计算机网络·html
鄃鳕4 小时前
python 字典 列表 类比c++【python】
c++·python
im_AMBER4 小时前
算法笔记 05
笔记·算法·哈希算法
夏鹏今天学习了吗4 小时前
【LeetCode热题100(46/100)】从前序与中序遍历序列构造二叉树
算法·leetcode·职场和发展
吃着火锅x唱着歌4 小时前
LeetCode 2389.和有限的最长子序列
算法·leetcode·职场和发展