【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.rhkb.cn/news/258131.html

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

相关文章

【Spring原理进阶】SpringMVC调用链+JSP模板应用讲解

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Spring 狂野之旅&#xff1a;底层原理高级进阶》 &#x1f680…

机器学习入门--循环神经网络原理与实践

循环神经网络 循环神经网络&#xff08;RNN&#xff09;是一种在序列数据上表现出色的人工神经网络。相比于传统前馈神经网络&#xff0c;RNN更加适合处理时间序列数据&#xff0c;如音频信号、自然语言和股票价格等。本文将介绍RNN的基本数学原理、使用PyTorch和Scikit-Learn…

PLC_博图系列☞FBD

PLC_博图系列☞FBD 文章目录 PLC_博图系列☞FBD背景介绍FBD优势局限性 FBD 元素 关键字&#xff1a; PLC、 西门子、 博图、 Siemens 、 FBD 背景介绍 这是一篇关于PLC编程的文章&#xff0c;特别是关于西门子的博图软件。我并不是专业的PLC编程人员&#xff0c;也不懂电路…

深度学习之梯度下降算法

梯度下降算法 梯度下降算法数学公式结果 梯度下降算法存在的问题随机梯度下降算法 梯度下降算法 数学公式 这里案例是用梯度下降算法&#xff0c;来计算 y w * x 先计算出梯度&#xff0c;再进行梯度的更新 import numpy as np import matplotlib.pyplot as pltx_data [1.0,…

心理辅导|高校心理教育辅导系统|基于Springboot的高校心理教育辅导系统设计与实现(源码+数据库+文档)

高校心理教育辅导系统目录 目录 基于Springboot的高校心理教育辅导系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、学生功能模块的实现 &#xff08;1&#xff09;学生登录界面 &#xff08;2&#xff09;留言反馈界面 &#xff08;3&#xff09;试卷列表界…

2.7日学习打卡----初学RabbitMQ(二)

2.7日学习打卡 目录&#xff1a; 2.7日学习打卡一. RabbitMQ 简单模式![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/42009c68e078440797c3183ffda6955d.png)生产者代码实现消费者代码实现 二. RabbitMQ 工作队列模式生产者代码实现消费者代码实现 三. RabbitMQ 发…

【天衍系列 04】深入理解Flink的ElasticsearchSink组件:实时数据流如何无缝地流向Elasticsearch

文章目录 01 Elasticsearch Sink 基础概念02 Elasticsearch Sink 工作原理03 Elasticsearch Sink 核心组件04 Elasticsearch Sink 配置参数05 Elasticsearch Sink 依赖管理06 Elasticsearch Sink 初阶实战07 Elasticsearch Sink 进阶实战7.1 包结构 & 项目配置项目配置appl…

《杨绛传:生活不易,保持优雅》读书摘录

目录 书简介 作者成就 书中内容摘录 良好的家世背景&#xff0c;书香门第为求学打基础 求学相关 念大学 清华研究生 自费英国留学 法国留学自学文学 战乱时期回国 当校长 当小学老师 创造话剧 支持钱锺书写《围城》 出任震旦女子文理学院的教授 接受清华大学的…

【AIGC】Stable Diffusion的ControlNet参数入门

Stable Diffusion 中的 ControlNet 是一种用于控制图像生成过程的技术&#xff0c;它可以指导模型生成特定风格、内容或属性的图像。下面是关于 ControlNet 的界面参数的详细解释&#xff1a; 低显存模式 是一种在深度学习任务中用于处理显存受限设备的技术。在这种模式下&am…

【AIGC】Stable Diffusion的模型入门

下载好相关模型文件后&#xff0c;直接放入Stable Diffusion相关目录即可使用&#xff0c;Stable Diffusion 模型就是我们日常所说的大模型&#xff0c;下载后放入**\webui\models\Stable-diffusion**目录&#xff0c;界面上就会展示相应的模型选项&#xff0c;如下图所示。作者…

【C++】 为什么多继承子类重写的父类的虚函数地址不同?『 多态调用汇编剖析』

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 前言 本篇文章主要是为了解答有…

Pytest测试技巧之Fixture:模块化管理测试数据

在 Pytest 测试中&#xff0c;有效管理测试数据是提高测试质量和可维护性的关键。本文将深入探讨 Pytest 中的 Fixture&#xff0c;特别是如何利用 Fixture 实现测试数据的模块化管理&#xff0c;以提高测试用例的清晰度和可复用性。 什么是Fixture&#xff1f; 在 Pytest 中&a…

华为问界M9:领跑未来智能交通的自动驾驶黑科技

华为问界M9是一款高端电动汽车&#xff0c;其自动驾驶技术是该车型的重要卖点之一。华为在问界M9上采用了多种传感器和高级算法&#xff0c;实现了在不同场景下的自动驾驶功能&#xff0c;包括自动泊车、自适应巡航、车道保持、自动变道等。 华为问界M9的自动驾驶技术惊艳之处…

Linux之多线程

目录 一、进程与线程 1.1 进程的概念 1.2 线程的概念 1.3 线程的优点 1.4 线程的缺点 1.5 线程异常 1.6 线程用途 二、线程控制 2.1 POSIX线程库 2.2 创建一个新的线程 2.3 线程ID及进程地址空间布局 2.4 线程终止 2.5 线程等待 2.6 线程分离 一、进程与线程 在…

构造题记录

思路&#xff1a;本题要求构造一个a和b数组相加为不递减序列&#xff0c;并且b数组的极差为最小的b数组。 可以通过遍历a数组并且每次更新最大值&#xff0c;并使得b数组为这个最大值和当前a值的差。 #include <bits/stdc.h> using namespace std; #define int long lon…

优化策略模式,提高账薄显示的灵活性和扩展性

接着上一篇文章&#xff0c;账薄显示出来之后&#xff0c;为了提高软件的可扩展性和灵活性&#xff0c;我们应用策略设计模式。这不仅仅是为了提高代码的维护性&#xff0c;而是因为明细分类账账薄显示的后面有金额分析这个功能&#xff0c;从数据库后台分析及结合Java语言特性…

小程序或者浏览器chrome访问的时候出现307 interval redicrect内部http自动跳转到https产生的原理分析及解决方案

#小李子9479# 出现的情况如下&#xff0c;即我们访问http的时候&#xff0c;它会自动307重定向到https,产生的原因是&#xff0c; 当你通过https访问过一个没有配置证书的http的网站之后&#xff0c;你再访问http的时候&#xff0c;它就会自动跳转到https&#xff0c;导致访问…

奔跑吧小恐龙(Java)

前言 Google浏览器内含了一个小彩蛋当没有网络连接时&#xff0c;浏览器会弹出一个小恐龙&#xff0c;当我们点击它时游戏就会开始进行&#xff0c;大家也可以玩一下试试&#xff0c;网址&#xff1a;恐龙快跑 - 霸王龙游戏. (ur1.fun) 今天我们也可以用Java来简单的实现一下这…

黄金交易策略(Nerve Nnife.mql4):移动止盈的设计

完整EA&#xff1a;Nerve Knife.ex4黄金交易策略_黄金趋势ea-CSDN博客 相较mt4的止盈止损&#xff0c;在ea上实现移动止盈&#xff0c;可以尽最大可能去获得更高收益。移动止盈的大体逻辑是&#xff1a;到达止盈点就开始追踪止盈&#xff0c;直到在最高盈利点回撤指定点数即平…

【Python】通过conda安装Python的IDE

背景 系统&#xff1a;win11 软件&#xff1a;anaconda Navigator 问题现象&#xff1a;①使用Navigator安装jupyter notebook以及Spyder IDE 一直转圈。②然后进入anaconda prompt执行conda install jupyter notebook一直卡在Solving environment/-\。 类似问题&#xff1a; …