【C++】类和对象---友元,内部类,匿名对象详解

目录

友元

友元函数

友元类

内部类

匿名对象



 ⭐友元

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以
友元不宜多用。
友元分为:友元函数友元类。

⚡友元函数

先看一个问题:

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

class Date
{
public:Date(int year, int month, int day): _year(year), _month(month), _day(day){}// d1 << cout; -> d1.operator<<(&d1, cout); 不符合常规调用
// 因为成员函数第一个参数一定是隐藏的this,所以d1必须放在<<的左侧ostream& operator<<(ostream& _cout){_cout << _year << "-" << _month << "-" << _day << endl;return _cout;}
private:int _year;int _month;int _day;
};

这是重载成成员函数后的写法:

这是重载成全局函数的写法:

友元函数可以直接访问类的私有成员,它是定义在类外部普通函数不属于任何类,但需要在类的内部声明,声明时需要加friend关键字

class Date
{friend ostream& operator<<(ostream& _cout, const Date& d);friend istream& operator>>(istream& _cin, Date& d);
public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}
private:int _year;int _month;int _day;
};
ostream& operator<<(ostream& _cout, const Date& d)
{_cout << d._year << "-" << d._month << "-" << d._day;return _cout;
}
istream& operator>>(istream& _cin, Date& d)
{_cin >> d._year;_cin >> d._month;_cin >> d._day;return _cin;
}
int main()
{Date d;cin >> d;cout << d << endl;return 0;
}

 说明:

  • 友元函数可访问类的私有和保护成员,但不是类的成员函数
  • 友元函数不能用const修饰
  • 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
  • 一个函数可以是多个类的友元函数
  • 友元函数的调用与普通函数的调用原理相同
     

⚡友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。

  • 友元关系是单向的,不具有交换性。(比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。就好像你把一个人当朋友,但是别人不把你当朋友😀)
  • 友元关系不能传递(如果C是B的友元, B是A的友元,则不能说明C时A的友元。)
  • 友元关系不能继承
class Time
{friend class Date; // 声明日期类为时间类的友元类,//则在日期类中就直接访问Time类中的私有成员变量
public: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 = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}void SetTimeOfDate(int hour, int minute, int second){// 直接访问时间类私有的成员变量_t._hour = hour;_t._minute = minute;_t._second = second;}
private:int _year;int _month;int _day;Time _t;
};

 ⭐内部类

概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,
不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越
的访问权限。

注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访
问外部类中的所有成员。但是外部类不是内部类的友元。(假如类B定义在类A内部,B可以访问A的成员,但是A不能访问B的成员)
特性:

  1. 内部类可以定义在外部类的public、protected、private都是可以的。
  2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
  3. sizeof(外部类)=外部类,和内部类没有任何关系。
     
class A
{
private:static int k;int h;
public:class B // B天生就是A的友元{public:void foo(const A& a){cout << k << endl;//OKcout << a.h << endl;//OK}};
};
int A::k = 1;
int main()
{A::B b;b.foo(A());return 0;
}

 ⭐匿名对象

匿名对象是在C++中创建的临时对象,没有被命名,通常用于临时操作或作为函数的实参或返回值。

特点:

  1. 临时对象:匿名对象通常是临时创建的,用于某个特定的操作或任务,不需要在程序中保留其状态或引用。

  2. 作为函数参数:匿名对象可以作为函数的参数传递,这样可以简化代码,避免创建额外的对象。

  3. 作为函数返回值:函数可以返回匿名对象,这样可以在调用函数时直接得到临时对象的值。
  4. 生命周期:匿名对象的生命周期通常很短,只在当前表达式或语句中有效(当前行)。一旦表达式或语句结束,匿名对象就会被销毁。因此,在使用匿名对象时要注意其生命周期,避免出现悬空指针或未定义行为。

class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};
class Solution {
public:int Sum_Solution(int n) {//...return n;}
};
int main()
{A aa1;// 不能这么定义对象,因为编译器无法识别下面是一个函数声明,还是对象定义//A aa1();// 但是我们可以这么定义匿名对象,匿名对象的特点不用取名字,// 但是他的生命周期只有这一行,我们可以看到下一行他就会自动调用析构函数A();A aa2(2);// 匿名对象在这样场景下就很好用,当然还有一些其他使用场景Solution().Sum_Solution(10);//如果不用匿名对象的方法,就需要先创建一个对象Solution s;s.Sum_Solution(10);return 0;
}

____________________

⭐感谢你的阅读,希望本文能够对你有所帮助。如果你喜欢我的内容,记得点赞关注收藏我的博客,我会继续分享更多的内容。⭐

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2804677.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

IntelliJ IDEA 创建Spring Boot 项目整合jdbc详细步骤

IntelliJ IDEA 创建Spring Boot 项目&整合jdbc详细步骤 1、打开 IntelliJ IDEA 软件2、使用 "Spring Initializr" 作为项目类型&#xff0c;新建项目工程3、选择对应的SpringBoot版本和依赖4、Spring Boot 项目的结构5、创建一个TestController&#xff0c;并运行…

Opencv实战(2)绘图与图像操作

Opencv实战(2)绘图与图像操作 指路前文&#xff1a;Opencv实战(1)读取与像素操作 三、基本绘图 文章目录 Opencv实战(2)绘图与图像操作三、基本绘图(1).line(2).rectangle(3).circle 四、图像处理(1).颜色空间1.意义2.cvtColor()3.inRange()4.适应光线 (2).形态操作1.腐蚀2.膨…

Spring中的ApplicationContext.publishEvent

简单理解 其实就是监听处理。比如找工作平台上&#xff0c;雇主 employer 发布自己的雇佣条件&#xff0c;目的是平台中有符合条件的求职者时&#xff0c;及时向雇主推荐。求职者发布简历&#xff0c;当平台发现某个求职者比较符合条件&#xff0c;就触发被动&#xff0c;推荐…

uni-app 经验分享,从入门到离职(五)——由浅入深 uni-app 数据缓存

文章目录 &#x1f4cb;前言⏬关于专栏 &#x1f3af;什么是数据存储&#x1f9e9;数据存储——存储&#x1f4cc; uni.setStorage(OBJECT)&#x1f4cc; uni.setStorageSync(KEY,DATA) &#x1f9e9;数据存储——获取&#x1f4cc; uni.getStorage(OBJECT)&#x1f4cc; uni.g…

vue 动态渲染本地图片不显示的解决方法

代码更改前 <img class"img" :src"/assets/images/${syntheticalGrade}.png" />data(){return{syntheticalGrade:"1"} }效果图&#xff1a; 解决代码 <img class"img" :src"require(/assets/images/${syntheticalGrad…

Atcoder ABC340 A-D题解

比赛链接:ABC340 话不多说&#xff0c;看题。 Problem A: 签到。 #include <bits/stdc.h> using namespace std; int main(){int a,b,d;cin>>a>>b>>d;for(int ia;i<b;id)cout<<i<<endl;return 0; } Problem B: 还是签到题。一个v…

2024-02-21 作业

作业要求&#xff1a; 复习课上内容 //已完成结构体字节对齐&#xff0c;64位没做完的做完&#xff0c;32位重新都做一遍&#xff0c;课上指定2字节对齐的做一遍&#xff0c;自己验证 //已完成两种验证大小端对齐的代码写一遍复习指针内容 //已完成完善顺序表已写出的…

记录 使用FFMPEG 笔记本摄像头推流

一、使用 FFMPEG 测试摄像头拉流显示 # 获取摄像头名称 ffmpeg -list_devices true -f dshow -i dummy# 我笔记本上的摄像头名称如下 device_pnp_\\?\usb#vid_0408&pid_1020&mi_00#6&199e90f7&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global# 使…

Python之Matplotlib

Matplotlib 是一个综合库&#xff0c;用于创建静态、动画、 和交互式可视化 安装 pip install matplotlib 功能 示例 import matplotlib.pyplot as plt plt.figure() plt.plot([1,2,3],[10,20,30]) plt.show() 官方文档&#xff1a; Matplotlib — Visualization with Pyt…

多窗口编程

六、多窗口编程 QMessageBox消息对话框&#xff08;掌握&#xff09; QMessageBox继承自QDialog&#xff0c;显示一个模态对话框。用于用户前台信息通知或询问用户问题&#xff0c;并接收问题答案。 QDialog的Qt源码中&#xff0c;派生类往往都是一些在特定场合下使用的预设好的…

MySQL数据库集群技术主从复制 一主一从详细讲解

集群技术 集群概述 MySQL复制技术 集群目的 负载均衡 解决高并发 高可用HA 服务可用性 远程灾备 数据有效性 类型 一主一从 一主双从 双主双从 原理 概念 在主库上把数据更改&#xff08;DDL DML DCL&#xff09;记录到二进制日志&#xff08;Binary Log&#xff09;中…

电路设计(28)——交通灯控制器的multisim仿真

1.功能设定 南北、东西两道的红灯时间、绿灯时间均为24S&#xff0c;数码管显示倒计时。在绿灯的最后5S内&#xff0c;黄灯闪烁。有夜间模式&#xff1a;按下按键进入夜间模式。在夜间模式下&#xff0c;数码管显示计数最大值&#xff0c;两个方向的黄灯不停闪烁。 2.电路设计 …

【EI会议征稿通知】2024年软件自动化与程序分析国际学术会议(SAPA 2024)

2024年软件自动化与程序分析国际学术会议&#xff08;SAPA 2024) 2024 International Conference on Software Automation and Program Analysis 在当今科技社会中&#xff0c;软件产业呈快速发展趋势&#xff0c;软件自动化与程序分析技术在提高软件质量、降低开发成本、提升…

fpga_cpu加速

一 cpu流水线执行指令 二 计算机体系结构 注&#xff1a;ARM就是典型的哈佛结构 三 cpu加速 同样采用流水线&#xff0c;哈佛结构的指令效率更高&#xff0c;通过指令预取&#xff0c;提高了流水线的并行度。

ROS1查看版本

目录 方法一方法二 方法一 rosversion -d方法二

[AutoSar]BSW_Com1 Can通信入门

目录 关键词平台说明一、车身CAN简介二、相关模块三、Can报文分类及信号流路径3.1 应用报文3.2 应用报文&#xff08;多路复用multiplexer&#xff09;3.3 诊断报文3.4 网络管理报文3.5 XCP报文&#xff08;标定报文&#xff09; 关键词 嵌入式、C语言、autosar、OS、BSW 平台…

微服务学习

一、服务注册发现 服务注册就是维护一个登记簿&#xff0c;它管理系统内所有的服务地址。当新的服务启动后&#xff0c;它会向登记簿交待自己的地址信息。服务的依赖方直接向登记簿要Service Provider地址就行了。当下用于服务注册的工具非常多ZooKeeper&#xff0c;Consul&am…

RT-Thread 时钟 timer delay 相关

前言 此处,介绍对delay 时钟 timer 这几部分之间的关联和相关的知识点;本来只是想介绍一下 delay的,但是发现说到delay 不先 提到 先验知识 晶振\时钟\时钟节拍\定时器 好像没法解释透彻,所以就变成了 晶振\时钟\时钟节拍\定时器\delay 的很简单的概括一遍;并附带上能直接运行的…

软件性能测试和功能测试有何联系和区别?第三方软件检测机构简析

软件性能测试和功能测试是软件开发过程中非常重要的两个环节。从根本上说&#xff0c;它们都是为了保证软件质量和可靠性&#xff0c;但它们的目标和方法却有所不同。 软件性能测试是评估软件在特定负载下的性能表现&#xff0c;包括响应时间、吞吐量、并发能力等指标。它通过…

LeetCode刷题日志-200.岛屿数量

思路&#xff1a; 遍历二维数组&#xff0c;每当遇到一个‘1’进行一次dfs&#xff0c;根据规则&#xff0c;将本次dfs到的所有元素标记为‘0’&#xff08;放置重复dfs&#xff0c;并且能dfs到的元素一定是与当前遍历到的元素属于统一岛屿。&#xff09;最后&#xff0c;dfs的…