【C++】友元、内部类和匿名对象

💗个人主页💗
⭐个人专栏——C++学习⭐
💫点击关注🤩一起学习C语言💯💫

目录

1. 友元

1.1 友元函数

1.2 友元类

2. 内部类

2.1 成员内部类

2.2 局部内部类

3. 匿名对象

3.1 基本概念

3.1 隐式转换


1. 友元

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

友元分为:友元函数友元类

1.1 友元函数

友元函数可以访问类的私有成员和受保护成员,即使它们不是类的成员函数。

友元函数在类中声明为友元,可以在类外部定义,但是它们可以访问类的私有和受保护成员。

友元函数的声明方式为将函数声明在类的声明内部,但不是类的成员函数,并使用关键字"friend"来标识它。

在类的外部定义友元函数时,不需要使用类名限定,直接定义即可。

class MyClass 
{
private:int num;
public:MyClass(int n) : num(n) {}friend void printNum(const MyClass& obj);
};void printNum(const MyClass& obj) 
{cout << "Num: " << obj.num << endl;  // 可以访问类的私有成员num
}int main() 
{MyClass obj(10);printNum(obj);  // 调用友元函数return 0;
}

友元函数的使用场景包括:

  1. 当某个函数需要访问类的私有成员时,可以将该函数声明为类的友元函数。
  2. 当需要重载运算符时,可以将重载函数声明为类的友元函数。
  3. 当需要在类的各个对象之间进行相互操作或访问私有数据时,可以使用友元函数。

友元函数的一个重要限制是,在类的声明内部声明为友元函数的函数需要在类之外定义。因此,友元函数不能直接访问类的成员变量和成员函数,需要使用对象的引用或指针来访问。

1.2 友元类

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

  • 友元关系是单向的,不具有交换性。
  • 友元关系不能传递 如果C是B的友元, B是A的友元,则不能说明C时A的友元。
  • 友元关系不能继承,在继承位置再给大家详细介绍。
class ClassA 
{
private:int numA;
protected:int numB;
public:ClassA(int a, int b) : numA(a), numB(b) {}friend class ClassB;
};class ClassB 
{
public:void printNum(const ClassA& obj) {cout << "NumA: " << obj.numA << endl;  // 可以访问类A的私有成员numAcout << "NumB: " << obj.numB << endl;  // 可以访问类A的受保护成员numB}
};int main() 
{ClassA objA(10, 20);ClassB objB;objB.printNum(objA);  // 调用友元类的成员函数return 0;
}

友元类的使用场景包括:

  1. 当一个类需要访问另一个类的私有成员时,可以将该类声明为友元类。
  2. 当需要在类之间进行相互操作或访问私有数据时,可以使用友元类。

2. 内部类

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

注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访 问外部类中的所有成员。但是外部类不是内部类的友元。

内部类可以分为两种类型:成员内部类和局部内部类。

特性:

  1. 内部类可以定义在外部类的public、protected、private都是可以的。
  2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
  3. sizeof(外部类)=外部类,和内部类没有任何关系。

2.1 成员内部类

成员内部类是在外部类的内部定义的一个类,它可以访问外部类的所有成员,包括私有成员。

成员内部类的定义通常放在外部类的声明中,但是它的实现需要在外部类的作用域之外进行。

class OuterClass
{
private:int _x;static int y;
public:OuterClass(int x = 10):_x(x){}class InnerClass{public:void display(OuterClass obj){cout << "x = " << obj._x << endl;cout << "y = " << y << endl;}};
};int OuterClass::y = 0; // 静态成员变量初始化int main() {OuterClass obj1;OuterClass::InnerClass obj2;obj2.display(obj1);return 0;
}

2.2 局部内部类

局部内部类是在函数或代码块内定义的一个类,它只在该函数或代码块的作用域内可见。

局部内部类可以访问外部类的所有成员,包括私有成员。

void outerMethod() 
{class LocalClass {public:void display() {cout << "This is a local inner class" << endl;}};LocalClass obj;obj.display();
}int main() 
{outerMethod();return 0;
}

3. 匿名对象

3.1 基本概念

匿名对象是指在创建对象时,没有为对象指定一个具体的名称,而是直接使用对象执行操作或调用方法。匿名对象在使用后就被销毁,无法再次引用。

class MyClass 
{
public:void display() {cout << "This is a MyClass object" << endl;}
};int main() 
{// 创建一个匿名对象并调用其display()方法MyClass().display();return 0;
}

3.1 隐式转换

C++中的匿名对象可以进行隐式转换。

隐式转换是指在某些情况下,编译器会自动将一个对象转换为目标类型,而无需显式地使用类型转换操作符。

1. 赋值操作:可以将匿名对象直接赋值给另一个对象。​​​​​​​​​​​​​​

class MyClass
{
public:MyClass(int value) : m_value(value) {}int getValue() { return m_value; }
private:int m_value;
};int main() {MyClass obj = MyClass(10); // 匿名对象被隐式转换并赋值给objcout << obj.getValue(); // 输出:10return 0;
}

2. 函数返回值:一个函数可以返回一个匿名对象,并且该匿名对象会被隐式转换为函数返回类型。

class MyClass 
{
public:MyClass(int value) : m_value(value) {}int getValue() { return m_value; }
private:int m_value;
};MyClass createObject() 
{return MyClass(10); // 返回一个匿名对象
}int main() 
{MyClass obj = createObject(); // 匿名对象被隐式转换并赋值给objcout << obj.getValue(); // 输出:10return 0;
}

3. 表达式中的运算:在一些表达式中,匿名对象可以参与运算,并且会被隐式转换为相应的类型。

class MyClass 
{
public:MyClass(int value) : m_value(value) {}int getValue() { return m_value; }MyClass operator +(const MyClass& other) {return MyClass(m_value + other.m_value); // 返回一个匿名对象}
private:int m_value;
};int main() 
{MyClass obj1(10);MyClass obj2(20);MyClass result = obj1 + obj2; // 匿名对象参与运算并被隐式转换为MyClasscout << result.getValue(); // 输出:30return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在已有代码基础上创建Git仓库

在已有代码基础上创建Git仓库 背景方法处理问题 背景 先进行了代码编写&#xff0c;后续想放入仓库方便大家一起合作开发&#xff0c;此时需要在已有代码的基础上建立仓库。 方法 首先在Gitee或者GitHub上创建仓库&#xff0c;这里以Gitee为例。创建完后&#xff0c;我们可以…

各类有关于花卉的深度学习数据集

花卉的识别和分类在深度学习过程中是最常见的使用的案例&#xff0c;因此各类有关花卉分类、识别、计数的图像数据集是大家都常用的数据集。最近收集到各类有关花卉的各类数据集分享给大家&#xff01;&#xff01; 1、16种花常见的图像数据集 数据说明&#xff1a;我们看到我…

Blazor SSR/WASM IDS/OIDC 单点登录授权实例1-建立和配置IDS身份验证服务

目录: OpenID 与 OAuth2 基础知识Blazor wasm Google 登录Blazor wasm Gitee 码云登录Blazor SSR/WASM IDS/OIDC 单点登录授权实例1-建立和配置IDS身份验证服务Blazor SSR/WASM IDS/OIDC 单点登录授权实例2-登录信息组件wasmBlazor SSR/WASM IDS/OIDC 单点登录授权实例3-服务端…

【实战】一、Jest 前端自动化测试框架基础入门(二) —— 前端要学的测试课 从Jest入门到TDD BDD双实战(二)

文章目录 一、Jest 前端自动化测试框架基础入门5.Jest 中的匹配器toBe 匹配器toEqual匹配器toBeNull匹配器toBeUndefined匹配器和toBeDefined匹配器toBeTruthy匹配器toBeFalsy匹配器数字相关的匹配器字符串相关的匹配器数组相关的匹配器异常情况的匹配器 6.Jest 命令行工具的使…

DSA 经典数据结构与算法 学习心得和知识总结(三) |有向无环图及其应用

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《算法导论》第三版 就是这本被封神的杰作&#xff0c;就是它&#x1f926; 2、参考书籍&#xff1a;《数据结构》严奶奶版 3、参考书…

DataX源码分析-插件机制

系列文章目录 一、DataX详解和架构介绍 二、DataX源码分析 JobContainer 三、DataX源码分析 TaskGroupContainer 四、DataX源码分析 TaskExecutor 五、DataX源码分析 reader 六、DataX源码分析 writer 七、DataX源码分析 Channel 八、DataX源码分析-插件机制 文章目录 系列文章…

基于GPT一键完成数据分析全流程的AI Agent: Streamline Analyst

大型语言模型&#xff08;LLM&#xff09;的兴起不仅为获取知识和解决问题开辟了新的可能性&#xff0c;而且催生了一些新型智能系统&#xff0c;例如旨在辅助用户完成特定任务的AI Copilot以及旨在自动化和自主执行复杂任务的AI Agent&#xff0c;使得编程、创作等任务变得高效…

Prompt Tuning:深度解读一种新的微调范式

阅读该博客&#xff0c;您将系统地掌握如下知识点&#xff1a; 什么是预训练语言模型&#xff1f; 什么是prompt&#xff1f;为什么要引入prompt&#xff1f;相比传统fine-tuning有什么优势&#xff1f; 自20年底开始&#xff0c;prompt的发展历程&#xff0c;哪些经典的代表…

CV | Segment Anything论文详解及代码实现

本文主要是详解解释了SAM的论文部分以及代码实现~ 论文&#xff1a;2023.04.05_Segment Anything 论文地址&#xff1a;2304.02643.pdf (arxiv.org) 代码地址&#xff1a;facebookresearch/segment-anything: The repository provides code for running inference with the Seg…

随机过程及应用学习笔记(四) 马尔可夫过程

马尔可夫过程是理论上和实际应用中都十分重要的一类随机过程。 目录 前言 一、马尔可夫过程的概念 二、离散参数马氏链 1 定义 2 齐次马尔可夫链 3 齐次马尔可夫链的性质 三、齐次马尔可夫链状态的分类 四、有限马尔可夫链 五、状态的周期性 六、极限定理 七、生灭过…

接口测试方法论

第1章 测试那点事 单元测试》接口测试》界面测试 接口就是包含特定输入和特定输出的一套逻辑处理单元&#xff0c;用户无须知晓接口的内部实现逻辑&#xff0c;这也可以称为接口的黑河处理逻辑。因为服务对象不同&#xff0c;接口又可分为两种&#xff1a;一种是系统或服务的…

K8S集群实践之十:虚拟机部署阶段性总结

目录 1. 说明&#xff1a; 2. 安装准备 2.1 每个节点设置双网卡&#xff0c;一卡做网桥&#xff08;外部访问&#xff09;&#xff0c;一卡做NAT&#xff08;集群内网访问&#xff09; 2.2 准备一个可用的代理服务器 3. 由于虚拟机崩溃&#xff08;停电&#xff0c;宿主机…

VBA技术资料MF119:数据验证的添加与删除

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

《苍穹外卖》知识梳理p7-用户下单与模拟微信支付

用户下单与微信支付 一.用户下单 1.1 订单表的设计 订单功能是一个核心的功能&#xff1b; 需要使用2张表&#xff1a; 1.订单表&#xff1a;记录一些订单信息&#xff0c;比如收货人&#xff0c;收获地址&#xff0c;支付金额&#xff0c;下单时间等&#xff1b; 2.订单详情…

GitLab配置SSHKey

段落一&#xff1a;什么是SSH密钥 SSH&#xff08;Secure Shell&#xff09;是一种网络协议&#xff0c;用于安全地远程登录和执行命令。SSH密钥是一种用于身份验证的加密文件&#xff0c;它允许您在与远程服务器通信时&#xff0c;无需输入密码即可进行认证。在GitLab中配置S…

Kibana:如何嵌入 Kibana 仪表板

作者&#xff1a;Carly Richmond 像我这样的前端工程师经常提出的要求是将 Kibana 等来源的现有仪表板嵌入到 JavaScript Web 应用程序中。 这是我必须多次执行的任务&#xff0c;因为我们希望快速部署用户生成的视图或允许用户控制给定的视图。 从我们从精彩的开发者社区收到的…

JVM(3)高级篇

1 GraalVM 1.1 什么是GraalVM GraalVM是Oracle官方推出的一款高性能JDK&#xff0c;使用它享受比OpenJDK或者OracleJDK更好的性能。 GraalVM的官方网址&#xff1a;https://www.graalvm.org/ 官方标语&#xff1a;Build faster, smaller, leaner applications。 更低的CPU、内…

Sora技术报告——Video generation models as world simulators

文章目录 1. 视频生成模型&#xff0c;可以视为一个世界模拟器2. 技术内容2.1 将可视数据转换成patches2.2 视频压缩网络2.3 Spacetime Latent Patches2.4 Scaling transformers 用于视频生成2.5 可变的持续时间&#xff0c;分辨率&#xff0c;宽高比2.6 抽样的灵活性2.7 改进框…

Invalid DataSize: cannot convert ‘30Mb‘ to Long

Invalid DataSize: cannot convert 30Mb to Long servlet:multipart:max-file-size: 30MBmax-request-size: 30MB