C++类和对象终章——友元函数 | 友元类 | 内部类 | 匿名对象 | 关于拷贝对象时一些编译器优化


文章目录
- 💐专栏导读
- 💐文章导读
- 🌷友元
- 🌺概念
- 🌺友元函数
- 🍁友元函数的重要性质
- 🌺友元类
- 🍁友元类的重要性质
- 🌷内部类(不常用)
- 🌺内部类的性质
- 🌷匿名对象
- 🌷关于拷贝对象时一些编译器优化
💐专栏导读
🌸作者简介:花想云,在读本科生一枚,致力于 C/C++、Linux 学习。
🌸本文收录于 C++系列,本专栏主要内容为 C++ 初阶、C++ 进阶、STL 详解等,专为大学生打造全套 C++ 学习教程,持续更新!
🌸相关专栏推荐:C语言初阶系列 、C语言进阶系列 、数据结构与算法
💐文章导读
本文为类和对象终章,我们将学习友元的概念,包含友元函数和友元类;内部类;匿名对象以及关于拷贝构造时一些编译器优化的情况等。
🌷友元
面向对象有三大特性——封装、继承、多态。从学习C++至今,我们一直在谈封装的重要性。但是在某些特殊的情况下,有时需要突破封装的限制。
🌼举例
之前我们通过实现日期类来学习运算符重载。其中实现操作符<<(流插入)、>>(流提取)的重载时,我们遇到了难题——如果在类中实现<<>>重载,我们无法调换this指针的位置,导致实现出来的重载<<用起来怪怪的。如下:
class Date
{
//...//使用因为返回,为了适应连续输入或输出的情况ostream& operator<<(ostream& out){out << _year << "年" << _month << "月" << _day << "日" << endl;return out;}istream& operator>>(istream& in){in >>_year >>_month >>_day;return in;}//...
}
void Test()
{Date d1(2023, 4, 1);d1 << cout;//有点奇怪
}
还记得当时我们是怎么解决的吗?答案是,可以将两个函数改为友元函数。例如:
class Date
{
//...//声明友元函数friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);//...
}
ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日";return out;
}istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}
上次我们只是浅浅的看了一下友元函数的使用。今天我们正式认识一下友元。
🌺概念
友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。
友元分为:友元函数和友元类。
🌺友元函数
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。
🌼示例
{
//...//声明友元函数friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);//...
}
ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日";return out;
}istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}
🍁友元函数的重要性质
友元函数有如下几条重要的性质:
- 友元函数可访问类的私有和保护成员,但它不是类的成员函数;
- 友元函数不能用
const修饰; - 友元函数可以在类定义的
任何地方声明,不受类访问限定符限制; 一个函数可以是多个类的友元函数;- 友元函数的调用与普通函数的调用原理相同;
🌺友元类
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
🌼示例
class Time
{friend class Date;//声明日期类为时间类的友元类,则在日期类中可以直接发访问时间类Time(int hour = 0, int minute = 0, int second = 0): _hour(hour), _minute(minute), _second(second){}
private:int _hour;int _minute;int _second;
};
class Date
{
public:Date(int year = 2023, int month = 4, int day = 9): _year(year), _month(month), _day(day){}void SetTime(int hour, int minute, int second){// 直接访问时间类私有的成员变量_t._hour = hour;_t._minute = minute;_t._second = second;}
private:int _year;int _month;int _day;Time _t;
};
🍁友元类的重要性质
友元类的重要性质如下:
友元关系是单向的,不具有交换性。
比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
友元关系不能传递;
如果C是B的友元, B是A的友元,则不能说明C是A的友元。
友元关系不能继承(先不做解释);
🌷内部类(不常用)
如果一个类定义在另一个类的内部,这个类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。
内部类有一个重要的性质——内部类天生就是外部类的友元。参照友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。
🌺内部类的性质
- 内部类可以定义在外部类的
public、protected、private下。 - 注意内部类可以直接访问外部类中的
static成员,不需要外部类的对象或类名。 sizeof(外部类)=外部类,说明外部类和内部类在空间上没有任何关系。
🌼示例
class A
{
private://声明static成员static int k;int n=0;
public:class B // B天生就是A的友元{public:void print(const A& a){cout << k << endl;cout << a.n << endl;}};
};//初始化static成员
int A::k = 1;int main()
{A::B b;//定义B类对象A a;b.print(a);return 0;
}
🌷匿名对象
匿名对象,顾名思义,该对象没有名字就叫匿名对象。匿名对象重要的性质:
匿名对象的生命周期只在定义它的那一行;
🌼示例
class A
{
public:A(int a = 0):_a(a){}
private:int _a;
};int main()
{//普通对象A a1;//匿名对象的定义return 0;
}
匿名对象看似鸡肋,但在某些场合下非常适用。比如,我们只想拿到类内部的某个成员的值,或只是想用一下类中的某个成员函数,为了一件简单的事而专门定义一个对象再销毁显得有点多此一举,那么就可以使用匿名对象。
🌼示例
class solution
{
public:int Sum_Solution(int n){int sum = 0;for (int i = 1; i <= n; i++){sum += i;}return sum;}
};
int main()
{//匿名对象的使用场景cout << solution().Sum_Solution(100) << endl;return 0;
}

🌷关于拷贝对象时一些编译器优化
对于有些场景下,若出现拷贝构造与构造同时出现的情况,编译器可能省略中间的拷贝构造,转化为直接构造。(此种情况取决于不同编译器不同的实现方法)
🌼示例
上一章中,我们谈到类型转换。这是典型的1个拷贝构造+1个构造优化为——>直接构造。
class Date
{
public:Date(int year):_year(year){}
private:int _year=0;
};void Test()
{//1个拷贝构造+1个构造优化为——>直接构造Date d2 = 2023;
}
🌼其它情况
class A
{
public:A(int a = 0):_a(a){}
private:int _a;
};void func1(A aa)
{}void func2(const A& aa)
{}A func3()
{A aa;return aa;
}A func4()
{return A();
}int main()
{A aa1 = 1; // 构造+拷贝构造 ——> 优化为直接构造func1(aa1); // 无优化func1(2); // 构造+拷贝构造 ——> 优化为直接构造func1(A(3)); // 构造+拷贝构造——> 优化为直接构造func2(aa1); // 无优化func2(2); // 无优化func2(A(3)); // 无优化A aa1 = func3(); // 拷贝构造+拷贝构造 -- 优化为一个拷贝构造A aa2;aa2 = func3(); // 不能优化func4(); // 构造+拷贝构造 -- 优化为直接构造A aa3 = func4(); // 构造+拷贝构造+拷贝构造 -- 优化为直接构造return 0;
}

点击下方个人名片,可添加博主的个人QQ,交流会更方便哦~
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
相关文章:
C++类和对象终章——友元函数 | 友元类 | 内部类 | 匿名对象 | 关于拷贝对象时一些编译器优化
文章目录💐专栏导读💐文章导读🌷友元🌺概念🌺友元函数🍁友元函数的重要性质🌺友元类🍁友元类的重要性质🌷内部类(不常用)🌺内部类的性…...
拼多多按关键字搜索商品 API
一、拼多多平台优势: 1、独创拼团模式 拼团拼单是拼多多独创的营销模式,其特点是基于人脉社交的裂变传播,非常具有传播性。 由于本身走低价路线,加上拼单折扣,商品的分享和人群裂变效果非常明显,电商前期…...
全链路日志追踪
背景 最近线上的日志全局追踪 traceId 不好使了,不同请求经常出现重复的 traceId,或者通过某个请求的 traceId 追踪搜索,检索出了与该请求完全不相干的日志。我领导叫我去排查解决这个问题,这里我把我排查的过程思路以及如何解决…...
ZYNQ:【1】深入理解PS端的TTC定时器(Part1:原理+官方案例讲解)
碎碎念:好久不见,甚是想念!本期带来的是有关ZYNQ7020的内容,我们知道ZYNQ作为一款具有硬核的SOC,PS端很强大,可以更加便捷地实现一些算法验证。本文具体讲解一下里面的TTC定时器,之后发布的Part…...
蓝牙设备如何自定义UUID
如何自定义UUID 所有 BLE 自定义服务和特性必须使用 128 位 UUID 来识别,并且要确保基本 UUID 与 BLE 定义的基本 UUID(00000000-0000-1000-8000-00805F9B34FB)不一样。基本 UUID 是一个 128 位的数值,根据该值可定义标准UUID&am…...
好看的html登录界面,
界面效果: 代码: <!DOCTYPE html> <html><head><title>Login Page</title><style>body {background-color: #f2f2f2;font-family: Arial, sans-serif;}form {background-color: #fff;border-radius: 5px;box-shado…...
Java模拟星空
目录 前言 JavaFX基础 1. GraphicsContext 2. AnimationTimer 代码实现 完整代码 前言 看了Python模拟星空很漂亮,Java也应该必须有一个! 环境:只需要JDK1.8就好!不需要外部包!!! Jav…...
YGG 代表 Web3 Gaming 参加 2023 年游戏开发者大会
Yield Guild Games(YGG)在 2023 年 3 月 20 日至 24 日在加州旧金山举行的游戏开发者大会(GDC)上大显身手,这是游戏开发者的重要交流学习活动。虽然 GDC 本身提供了多种多样的活动,包括讲座、小组讨论、圆桌…...
水库安全运行智慧管理平台解决方案筑牢防汛“安全墙”
解决方案 水库安全运行智慧管理系统解决方案,系统主要由降雨量监测站、水库水位监测站、大坝安全监测中的渗流量、渗流压力和变形监测站及视频和图像监测站等站点组成,同时建立规范、统一的监测平台,集数据传输、信息共享、数据储存于一体&a…...
Exchange升级部署方案
目录 前言 一、需求分析 二、升级前准备 1.备份当前 Exchange Server 数据...
AE开发之图层渲染20210603
AE开发之图层渲染比例符号化地图的整饰唯一值符号的符号化过程点符号设置,线符号设置标注图层,(写得不好,不推荐看) 唯一值符号化,字段进行设置,这里用到了UniqueValueRenderer接口,这里面有一…...
需要了解的过滤器
过滤器 1. 概念 过滤器: 从名字上理解就是对于事件的过滤操作,在web 中的过滤器,就是对于请求进行过滤操作,我们使用过滤器,就可以对于请求进行拦截操作,然后进行响应的处理操作,实现很多的特殊…...
VUE3的setup函数
文章目录 目录 文章目录 前言 一、setup函数是什么? 二、使用步骤 三、vue3中文文档和面向vue3的组件库 总结 前言 Vue3是一个面向数据驱动的渐进式JavaScript框架,其的设计理念包括简洁、灵活和高效。相比Vue2,Vue3的架构设计有很大的不同&…...
停车场管理系统文件录入(C++版)
❤️作者主页:微凉秋意 ✅作者简介:后端领域优质创作者🏆,CSDN内容合伙人🏆,阿里云专家博主🏆 文章目录一、案例需求描述1.1、汽车信息模块1.2、普通用户模块1.3、管理员用户模块二、案例分析三…...
线程(Thread)的三种等待唤醒机制详解
1、为什么需要线程的等待和唤醒 线程的等待唤醒机制是一种经典的“生产者和消费者”模型。例如食品加工厂,食品加工人员和原料补给人员,在有充足原料时,补给人员是在等待,等到原料不够时,食品加工人员通知补给人员&am…...
从零学习python - 13模块的导入与使用(实现单例模式)
模块基础知识 # 项目 > 包 > 模块 > 变量\方法\类 # 在python中,模块是代码组织的一种方式,把功能相近的函数或类放到一个文件中,一个文件(.py)就是一个模块,模块名就是文件名去掉py后缀. # 好处:提高代码可复用性和可维护性,一个模块编写完成后,很方便在其他项目中导…...
国产SSD、内存卷哭国外大厂,三星宣布减产涨价在路上了
PC 圈有一句话是这么说的:论价格屠夫还得看国产品牌! 可不是嘛,国产长鑫、长江算是彻底将全球存储芯片市场搅局者这一「骂名」坐实了! 不说特别早期,前几年吧,普通单条 8G DDR4 内存都能卖到六七百元&…...
数据库管理-第六十六期 SQL Domain(20230413)
数据库管理 2023-04-13第六十六期 SQL Domain1 基本介绍2 Domain的表达式和条件3 语法4 语义5 示例总结第六十六期 SQL Domain 上一期一笔带过了部分Oracle 23c的新特性,这一期重点讲一下SQL Domain新特性。 【https://docs.oracle.com/en/database/oracle/oracle-…...
《Vue3实战》 第一章 nods/npm安装、配置
1、nods.js安装(Windows) 1.1、下载并安装node https://nodejs.org/en/ , 安装到d盘nodejs目录 1.2、配置环境变量 path配置 1.3、配置全局包存放目录和缓存目录 在根目录下创建node_global(全局包存放目录)和node_cache&…...
JAVA练习104-四数相加 II
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、题目-四数相加 II 1.题目描述 2.思路与代码 2.1 思路 2.2 代码 总结 前言 提示:这里可以添加本文要记录的大概内容: 4月10日练…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
