当前位置: 首页 > news >正文

C++友元

采用类的机制后实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,成员函数一般定义为公有的,依据提供类与外界间的通讯接口
但是,有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁的访问类的数据成员,这时可以将这些函数定义为该类的友元函数。除了友元函数外,还有友元类,统称为友元。
友元的作用是提高程序的运行效率,但它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。
友元可以是一个函数,该函数称为友元函数,友元也可以是一个类,成为友元类

1. 同类对象间无友元

MyString::MyString(const MyString &other) 
{int len = strlen(other._str);this->_str = new char[len+1];strcpy(this->_str, other._str);
}

2. 异类对象间有友元

友元目的本质是让其他不属于本类的成员(全局函数,其他类的成员函数),成为类的成员而具备了本类成员的属性

2.1. 友元函数

友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,它不属于任何类,但需要在类中定义加以声明,声明时只需在友元的名称前加上关键字friend,格式如下:

friend 类型 函数名(形式参数);

一个函数可以是多个类的友元函数,只需要在各个类中分别声明

2.1.1. 全局函数作友元函数

class Point
{
public:Point(double xx, double yy){x = xx;y = yy;}void Getxy();friend double Distance(Point &a, Point &b);private:double x, y;
};
void Point::Getxy()
{cout << "(" << x << "," << y << ")" << endl;
}
double Distance(Point &a, Point &b)
{double dx = a.x + b.x;double dy = a.y + b.y;return sqrt(dx * dx + dy * dy);
}
int main()
{Point p1(3.0, 4.0), p2(5.0, 6.0);p1.Getxy();p2.Getxy(); double d = Distance(p1, p2);cout << "Distance is " << d << endl; return 0;
}

2.1.2. 类成员函数作友元函数

class Point;class ManagerPoint
{
public:double Distance(Point &a, Point &b);
};
class Point
{
public:Point(double xx, double yy){x = xx;y = yy;}void Getxy();friend double ManagerPoint::Distance(Point &a, Point &b);private:double x, y;
};
void Point::Getxy()
{cout << "(" << x << "," << y << ")" << endl;
}
double ManagerPoint::Distance(Point &a, Point &b)
{double dx = a.x - b.x;double dy = a.y - b.y;return sqrt(dx * dx + dy * dy);
}
int main()
{Point p1(3.0, 4.0), p2(5.0, 6.0);p1.Getxy();p2.Getxy();ManagerPoint mp;float d = mp.Distance(p1, p2);cout << "Distance is " << d << endl; return 0;
}

补充:
前向声明:是一种不完全型声明,即只需提供类名(无需提供类实现)即可。因此功能也很有限:
1. 不能定义类的对象
2. 可以用于定义指向这个类型的指针或引用
3. 用于声明(不是定义),使用该类型作为行参类型或者函数的返回值类型

2.2. 友元类

友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)
当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类,定义友元类的格式如下:

friend class 类名;
其中,friendclass是关键字,类名必须是程序中一个已定义过的类
例如,以下语句说明类B是类A的友元类:
class A 
{public:: friend class B;
}

类B的所有成员函数都是类A的友元函数,能存取类A的私有成员和保护成员

class AA
{
public:inline void Test(){}private:int x, y;friend class BB;
};
class BB
{
public:inline void Test(){AA a;printf("x = %d, y = %d\n", a.x, a.y);}
};

3. 论友元

3.1. 声明位置

友元声明以关键字friend开始,只能出现在类定义中,因为友元不是授权类的成员,所以不受其所在类的声明区域public private和protected的影响。通常选择把所有友元声明组织在一起并放在类头之后。

3.2. 友元的利弊

友元不是类成员,但可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是它破坏了类的封装行和隐藏性,使得非成员函数可以访问类的私有成员。不过,类的访问权限确实在某些应用场合显得有些呆板,从而容忍了友元这一语法现象

3.3. 注意事项

  1. 友元关系不能被继承
  2. 友元关系是单向的不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明
  3. 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的声明

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • mysql5.6的安装步骤
  • PyCharm 安装
  • 【C++】类型擦除 + 工厂模式,告别 if-else
  • My sql 安装,环境搭建
  • 【C++PCL】点云处理误差RMSE值计算
  • Spring Boot与RSocket的集成
  • IDEA常用技巧荟萃:精通开发利器的艺术
  • 字符串中的注意事项
  • Postman深度解析:打造高效接口测试自动化流程
  • firewalld(6)自定义services、ipset
  • Spring 使用 Ehcache 技术指南
  • OFDM中采样频率与带宽的关系
  • 什么是设计模式以及常见的例子(如单例、工厂、观察者等)
  • IT高手修炼手册(3)程序员命令
  • 如何在Java中实现实时数据同步与更新
  • 2017-08-04 前端日报
  • CentOS7简单部署NFS
  • docker容器内的网络抓包
  • ES学习笔记(10)--ES6中的函数和数组补漏
  • javascript面向对象之创建对象
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • Laravel Mix运行时关于es2015报错解决方案
  • maya建模与骨骼动画快速实现人工鱼
  • php的插入排序,通过双层for循环
  • Rancher如何对接Ceph-RBD块存储
  • Selenium实战教程系列(二)---元素定位
  • SQLServer插入数据
  • V4L2视频输入框架概述
  • vagrant 添加本地 box 安装 laravel homestead
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • windows-nginx-https-本地配置
  • 从setTimeout-setInterval看JS线程
  • 番外篇1:在Windows环境下安装JDK
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 高性能JavaScript阅读简记(三)
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 入门级的git使用指北
  • 通过npm或yarn自动生成vue组件
  • 你对linux中grep命令知道多少?
  • 京东物流联手山西图灵打造智能供应链,让阅读更有趣 ...
  • ​探讨元宇宙和VR虚拟现实之间的区别​
  • ‌分布式计算技术与复杂算法优化:‌现代数据处理的基石
  • #APPINVENTOR学习记录
  • #NOIP 2014#Day.2 T3 解方程
  • #每天一道面试题# 什么是MySQL的回表查询
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (2024.6.23)最新版MAVEN的安装和配置教程(超详细)
  • (3)STL算法之搜索
  • (二)WCF的Binding模型
  • (二刷)代码随想录第15天|层序遍历 226.翻转二叉树 101.对称二叉树2
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (十一)JAVA springboot ssm b2b2c多用户商城系统源码:服务网关Zuul高级篇
  • (提供数据集下载)基于大语言模型LangChain与ChatGLM3-6B本地知识库调优:数据集优化、参数调整、Prompt提示词优化实战
  • (图)IntelliTrace Tools 跟踪云端程序