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

C++ 类和对象(友元、内部类、匿名对像)

目录

一、前言

二、正文

1.友元

1.1友元函数的使用

1.1.1外部友元函数可访问类的私有成员,友员函数仅仅是一种声明,他不是类的成员函数。

1.1.2一个函数可以是多个类的友元函数

2.友元类的使用

2.1什么是友元类

2.2 友元类的关系是单向的,不具有交换性。

2.3 友元类关系不能传递。

3.内部类

3.1内部类的使用

3.1.1 由于内部类是一个独立的类,跟定义在全局相比,它只是受外部类类域限制和访问限定符限制,所以外部定义的对象不包含内部类。

3.1.2内部类默认是外部类的友元类

4.匿名对象

4.1匿名对象的应用场景


一、前言

昨天我们已经分享了类和对象中类型转换和static成员的知识,有兴趣的小伙伴可以看一下:

https://blog.csdn.net/yiqingaa/article/details/144066165

今天让我们在一起学习类和对象中的友元、内部类,和匿名对象吧。

二、正文

1.友元

  • 友元提供了一种突破类访问限定符封装的方式,友元分为:友元函数和友元类,在函数声明或者类声明的前面加friend,并且把友元声明放到一个类的里面。
  • 外部友元函数可访问类的私有和保护成员,友元函数仅仅是一种声明,他不是类的成员函数。
  • 友元函数可以在类定义的任何地方声明,不受类访问限定符限制。
  • 一个函数可以是多个类的友元函数。
  • 友元类中的成员函数都可以是另一个类的友元函数,都可以访问另一个类中的私有和保护成员。
  • 友元类的关系是单向的,不具有交换性,比如A类是B类的友元,但是B类不是A类的友元。
  • 友元类关系不能传递,如果A是B的友元,B是C的友元,但是A不是C的友元。
  • 有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。 

1.1友元函数的使用

 从上图可以看出在我们的Print函数中系统爆出了警告,说A::_a1、A::_a2是不可访问的。那是因为_a1、_a2被限定符private给限制住了,在类外面无法访问类里面的私有成员(这里是_a1和_a2)那么我们如何在类外面定义的函数访问我们的私有成员呢?这里我们就可以借助我们的友元函数来解决这个问题:

#include<iostream>
using namespace std;
class A
{
public:friend void Print(const A& aa);//我们只需要把函数抄写一下放在类里面,然后前面加个friend就行。A(int a1 = 1, int a2 = 2){_a1 = a1;_a2 = a2;}
private:int _a1;int _a2;
};
void Print(const A& aa)
{cout << aa._a1 << " " << aa._a2 << endl;
}
int main()
{A a;Print(a);return 0;
}

友元函数的使用方法很简单,只需要把定义在类外面的函数抄写一份到类里面,然后在函数前面加个friend就行了,friend+函数->友元函数(前提是这个函数定义在类外面,不然这么做其实无实际意义,毕竟如果这个函数是定义在类里面的,直接就可以调用私有成员。没必要多此一举)

  • 友员函数可以这么理解:之前我们是陌生人,我去你家里玩,私闯民宅这是违法的。不过现在我们是朋友了(我是你的友元函数,如上图中Print是类A的友元函数,即Print是A的朋友)那么我去你家玩,就没有任何问题了。
  • 友元可以定义在类里面的任何地方,哪怕是定义在限制符private里面都没问题,不过个人建议放在类里面的第一行,易于让人知道:哦,你使用了友元函数(清晰明了)。

  • 1.1.1外部友元函数可访问类的私有成员,友员函数仅仅是一种声明,他不是类的成员函数。

如图所示,当我们想要通过  类名+::的方式去访问类中的公共成员的时候,只发现了类A的构造函数,而没有发现Print,这说明了友员函数仅仅只是一种声明,而非是这个类的成员函数。

  • 1.1.2一个函数可以是多个类的友元函数
#include<iostream>
using namespace std;
class B;
class A
{
public:friend void Print(const A& aa,const B& bb);//Print是A的盆友A(int a1 = 1, int a2 = 2){_a1 = a1;_a2 = a2;}
private:int _a1;int _a2;
};
class B
{
public:friend void Print(const A& aa, const B& bb);//Print是B的盆友B(int b1 = 3, int b2 = 4){_b1 = b1;_b2 = b2;}
private:int _b1;int _b2;
};
void Print(const A& aa,const B& bb)
{cout << aa._a1 << " " << aa._a2 << endl;cout << bb._b1 << " " << bb._b2 << endl;
}
int main()
{A a;B b;Print(a,b);return 0;
}

由上图可知,函数Print不仅是类A的盆友,同时也是类B的盆友。就像一个人可以是很多人的盆友一样,并不是独属于你的盆友。

2.友元类的使用

  • 2.1什么是友元类

定义:一个类可以将另一个类声明为它的友元类,被声明为友元的类将获得对原始类所有成员的访问权限,无论是私有、保护还是公有成员  。

#include<iostream>
using namespace std;
class B;
class A
{
public:friend class B;//这里我们直接让B整个类都是A的盆友,这样我们不仅在Fun1函数中能使用A中隐私变量,在Func2中也能使用A中隐私成员。A(int a1 = 1, int a2 = 2){_a1 = a1;_a2 = a2;}void Func1(){cout<< _a1 << " " << _a2 << endl;}
private:int _a1;int _a2;
};
class B
{
public:B(int b1 = 3, int b2 = 4){_b1 = b1;_b2 = b2;}void Func2(const A& aa){cout << aa._a1 << " " << aa._a2 << endl;}void Func3(const A& aa){cout << aa._a1 << " " << aa._a2 << endl;}
private:int _b1;int _b2;
};
int main()
{A a;B b;b.Func2(a);b.Func3(a);return 0;
}

就例如上图所示,如果我们想在B类中任意使用A中的私有成员(_a1和_a2)我们可以让B一整个类都成为类A的友元,这样我们不仅让类B中的Func1能访问到A中的私有成员(_a1和_a2),Func2中也能访问到A中的私有成员(_a1和_a2)。

  • 2.2 友元类的关系是单向的,不具有交换性。

比如A类是B类的友元,但是B类不是A类的友元,我们如果想要在A类中访问B中私有成员(_b1和_b2)就访问不到。

  • 2.3 友元类关系不能传递。

如果A是B的友元,B是C的友元,但是A不是C的友元。

可以理解为我是你的盆友,你是他的盆友,但这并不意味着,我和他就是盆友。

3.内部类

  • 如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,跟定义在全局相比,他只是受外部类类域限制和访问限定符限制,所以外部类定义的对象中不包含内部类。
  • 内部类默认是外部类的友元类。
  • 内部类本质也是一种封装,当A类跟B类紧密关联,A类实现出来主要就是给B类使用,那么可以考虑把A类设计为B的内部类,如果放到private/protected位置,那么A类就是B类的专属内部类,其他地方都用不了。 
3.1内部类的使用

#include<iostream>
using namespace std;
class A
{
public:A(int a1 = 1, int a2 = 2){_a1 = a1;_a2 = a2;}void Func1()const{cout<< _a1 << " " << _a2 << endl;}class B{public:B(int b1 = 3, int b2 = 4){_b1 = b1;_b2 = b2;}void Func2(const A&aa){cout <<aa. _a1 << " " << aa._a2 << endl;}void Func3(const A& aa){cout << aa._a1 << " " << aa._a2 << endl;}private:int _b1;int _b2;};
private:int _a1;int _a2;
};
class B
{
public:B(int b1 = 3, int b2 = 4){_b1 = b1;_b2 = b2;}
private:int _b1;int _b2;
};
int main()
{A a;return 0;
}

上面就是我们简单的写了个内部类。类B被定义在类A的内部。

  • 3.1.1 由于内部类是一个独立的类,跟定义在全局相比,它只是受外部类类域限制和访问限定符限制,所以外部定义的对象不包含内部类。

看图可知,外部定义的对象a中没有类B,只有成员函数Fun1。

  • 3.1.2内部类默认是外部类的友元类

因为B被定义在A中,所以B是A的盆友,即在B中可以任意访问到A中的私有成员。

例如:B中的Func2和Func1都能访问到A的私有成员(_a1和_a2)。

4.匿名对象

  • 用类型(实参)定义出来的对象叫做匿名对象,相比之前我们定义的 类型 对象名(实参) 定义出来的叫有名对象。
  • 匿名对象生命周期只在当前一行,一般临时定义一个对象当前用一下即可,就可以定义匿名对象。 

如上图所示,就是有名对象和匿名对象的区别。

值得注意的是:匿名对象的生命周期,只有该匿名对象创建的哪一行,一旦运行到下一行,该匿名对象就被销毁了。

4.1匿名对象的应用场景

匿名对象的使用主要是方便。例如:

我们只是想调用一下成员函数Func1:

  1. 创造有名对象a,再通过实例化对象a访问Func1,需要两行代码。如上图标号1。
  2. 直接创造匿名对象,直接访问Func1,只需要一行代码。如上图标号。

现在知道匿名对象的作用了吗,其实就是为了图方便,能写一行代码完成的事情,为什么要写两行呢,对吧。

三结言

本次博客的分享就到这呢,同学们咱们下次再见,拜拜喽。

相关文章:

C++ 类和对象(友元、内部类、匿名对像)

目录 一、前言 二、正文 1.友元 1.1友元函数的使用 1.1.1外部友元函数可访问类的私有成员&#xff0c;友员函数仅仅是一种声明&#xff0c;他不是类的成员函数。 1.1.2一个函数可以是多个类的友元函数 2.友元类的使用 2.1什么是友元类 2.2 友元类的关系是单向的&#x…...

PostgreSQL 常用函数

PostgreSQL 常用函数 在数据库管理系统中&#xff0c;函数是执行特定任务的基本构建块。PostgreSQL 是一个功能强大的开源关系数据库管理系统&#xff0c;提供了丰富的内置函数&#xff0c;这些函数极大地增强了数据库操作的能力。以下是一些在 PostgreSQL 中常用的函数&#…...

掌握 ElasticSearch 四种match查询的原理与应用

文章目录 一、引言 (Introduction)二、准备工作&#xff1a;创建索引和添加示例数据三、match 查询四、match_all 查询五、multi_match 查询六、match_phrase 查询七、总结 (Conclusion) 一、引言 (Introduction) 在信息爆炸的时代&#xff0c;快速准确地找到所需信息至关重要…...

解决:Conda虚拟环境中未设置CUDA_HOME的问题

背景&#xff1a;我是Ubuntu22.04系统&#xff0c;最近在复现FoundationPose算法&#xff0c;按照README构建部署环境时&#xff0c;有一步一直卡住&#xff0c;看了下是未找到CUDA_HOME这个环境变量。 网上搜了下这个错误&#xff0c;需要设置CUDA_HOME的环境变量路径&#x…...

easyexcel和poi同时存在版本问题,使用easyexcel导出excel设置日期格式

这两天在使用easyexcel导出excel的时候日期格式全都是字符串导致导出的excel列无法筛选 后来调整了一下终于弄好了&#xff0c;看一下最终效果 这里涉及到easyexcel和poi版本冲突的问题&#xff0c;一直没搞定&#xff0c;最后狠下心来把所有的都升级到了最新版&#xff0c;然…...

HarmonyOS 开发套件 介绍——下篇

HarmonyOS 开发套件 介绍——下篇 在HarmonyOS的生态中&#xff0c;开发套件作为支撑整个系统发展的基石&#xff0c;为开发者提供了丰富而强大的工具和服务。本文将深入继续介绍HarmonyOS SDK、ArkCompiler、DevEco Testing、AppGallery等核心组件&#xff0c;帮助开发者全面掌…...

关于order by的sql注入实验

实验描述 本实验基于sqli-lab的第46关进行测试 本关的sql 语句为$sql "SELECT * FROM users ORDER BY $id" 利用sort进行sql注入&#xff0c;我们可以利用报错注入&#xff0c;延时注入来爆出数据 1.报错注入 1.手工测试 爆出数据库 ?sort(extractvalue(1, c…...

Transformers快速入门-学习笔记

一、自然语言处理 NLP 是借助计算机技术研究人类语言的科学自然语言处理发展史 一、不懂语法怎么理解语言 依靠语言学家人工总结文法规则 Chomsky Formal Languages 难点&#xff1a;上下文有关文法 规则增多&#xff0c;存在矛盾 二、只要看得足够多&#xff0c;就能处理语言…...

luci界面开发中的MVC架构——LuCI介绍(二)

想要给openwrt开发应用&#xff0c;虽然直接可执行程序也可以运行&#xff0c;但是没有UI会很不方便&#xff0c;想要开发UI就要用openwrt的那一套&#xff0c;自然就是LuCI&#xff0c;LuCI又用了一套MVC框架&#xff0c;今天就讲讲这是个什么东西。 OpenWrt LuCI 界面开发中…...

第1章大型互联网公司的基础架构——1.10 其他NoSQL数据库

这里我们简单介绍一下其他常见的NoSQL数据库及其适用的场景&#xff0c;其中部分数据库会在后续服务设计章节中正式使用时再做详细介绍。 1.10.1 文档数据库 文档数据库的典型代表是MongoDB和CouchDB。**文档数据库普遍采用JSON格式来存储数据&#xff0c;而不是采用僵硬的行…...

DeepSeek+Kimi生成高质量PPT

DeepSeek与Kimi生成PPT全流程解析 一、工具分工原理 DeepSeek核心作用&#xff1a;生成结构化PPT大纲&#xff08;擅长逻辑构建与内容优化&#xff09;Kimi核心作用&#xff1a;将文本转换为视觉化PPT&#xff08;提供模板库与排版引擎&#xff09; 二、操作步骤详解 1. 通…...

web网络安全:跨站脚本攻击(XSS)

跨站脚本攻击&#xff08;XSS&#xff09;概述 跨站脚本攻击&#xff08;XSS&#xff0c;Cross-Site Scripting&#xff09; 是一种常见的 Web 安全漏洞&#xff0c;攻击者通过向受信任的网站注入恶意脚本&#xff08;通常是 JavaScript&#xff09;&#xff0c;诱使其他用户在…...

【Python爬虫(44)】分布式爬虫:筑牢安全防线,守护数据之旅

【Python爬虫】专栏简介&#xff1a;本专栏是 Python 爬虫领域的集大成之作&#xff0c;共 100 章节。从 Python 基础语法、爬虫入门知识讲起&#xff0c;深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑&#xff0c;覆盖网页、图片、音频等各类数据爬取&#xff…...

微信小程序:多菜单栏设计效果

一、实现效果 二、代码 wxml 编辑前端界面,步骤 菜单逻辑: 逐步取出数组中的项,首先取出顶部菜单项,然后选中后取出选中的底部数据(左侧菜单+右侧内容),然后点击左侧菜单取出选中的左侧菜单对应的右侧内容 ①这里我的数据是全部封装到一个数组对象的,首先我的循环…...

海康威视摄像头ISUP(原EHOME协议) 摄像头实时预览springboot 版本java实现,并可以在浏览器vue前端播放(附带源码)

1.首先说了一下为什么要用ISUP协议来取流 ISUP主要就是用来解决摄像头没有公网ip的情况,如果摄像头或者所在局域网的路由器有公网ip的话&#xff0c;其实采用rtsp直接取流是最方便也是性能最好的&#xff0c;但是项目的摄像头没有公网IP所以被迫使用ISUP&#xff0c;ISUP是海康…...

蓝桥杯之阶段考核

&#x1f4d6; Day 7&#xff1a;阶段考核 - 蓝桥杯官方模拟赛&#xff08;限时 4 小时&#xff09; &#x1f4d6; 一、如何高效完成模拟赛&#xff1f; 模拟赛是一种接近真实竞赛的训练方式。要高效完成模拟赛&#xff0c;需要掌握以下策略&#xff1a; 1. 赛前准备 ✅ 环…...

Python爬虫基础重要数据类型

重要数据类型 列表数据类型 在实际开发中&#xff0c;经常需要将一组&#xff08;不只一个&#xff09;数据存储起来&#xff0c;以便后边的代码使用。列表就是这样的一个数据结构。且列表是Python中最基本也是最常用的数据结构之一。什么是数据结构呢&#xff1f;通俗来讲&a…...

乐享数科:供应链金融—三个不同阶段的融资模式

供应链金融是与产业链紧密结合的融资模式&#xff0c;它主要体现在订单采购、存货保管、销售回款这三个不同的业务阶段&#xff0c;并针对这些阶段提供了相应的金融服务。以下是这三个阶段中主要的融资模式及其特点&#xff1a; 供应链金融融资模式主要分为以下几种&#xff1…...

【AI】openEuler 22.03 LTS SP4安装 docker NVIDIA Container Toolkit

NVIDIA Container Toolkit 打开网址 Unsupported distribution or misconfigured repository settings | NVIDIA Container Toolkit 为方便离线安装&#xff0c;先下载过来 wget https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo mk…...

【2025全网首发B站教程】YOLOv12训练数据集构建:标签格式转换-划分-YAML 配置 避坑指南 | 小白也能轻松玩转目标检测!

【2025全站首发】YOLOv12训练数据集构建&#xff1a;标签格式转换-划分-YAML 配置 避坑指南 | 小白也能轻松玩转目标检测&#xff01; 文章目录 1. 数据集准备1.1 标签格式转换1.2 数据集划分1.3 yaml配置文件创建 2. 训练验证 1. 数据集准备 示例数据集下载链接&#xff1a;P…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...