C++ 内部类

news2024/11/27 22:45:39

 个人主页:Jason_from_China-CSDN博客

所属栏目:C++系统性学习_Jason_from_China的博客-CSDN博客

所属栏目:C++知识点的补充_Jason_from_China的博客-CSDN博客

概念概述

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

内部类的使用1

正常代码

class A
{
public:
	A();
	~A();

private:

};

class B
{
public:
	B();
	~B();

private:

};

内部类的代码

#include<iostream>
using namespace std;
class A
{
public:
	A(int a1 = 1, int a2 = 1) 
		:_a1(a1)
		,_a2(a2)
	{};

	class B
	{
	public:
		//错误写法,内部类和外部类是相对独立的,是不能直接访问的
		//B(int b1 = _a1, int b2 = _a2)

		//B()
		//{}


		直接访问类(这里没有默认构造)
		//B(const A a)
		//	:_b1(a._a1)
		//	,_b2(a._a2)
		//{}

		//默认构造写法
		B(int b1 = 2, int b2 = 2)
			:_b1(b1)
			,_b2(b2)
		{}
		void _print()
		{
			cout << "内部类默认是外部类的友元函数" << endl;
		}
	private:
		int _b1;
		int _b2;
	};
private:
	int _a1 = 1;
	int _a2 = 1;
};



int main()
{
	A a;
	A::B b;

	return 0;
}

注意事项:

  • 内部类和外部类是相对独立的,外部类构造时,不能直接将构造的数值传递给内部类。外部类先构造,但在外部类构造函数执行时,内部类的对象可能还未创建,内部类的作用域在外部类内部,外部类构造函数不能直接访问还未创建的内部类对象的成员。
    下图我们就可以看出来,我们直接从外部类构造的数值去初始化内部类是不能成功的,需要默认构造函数

但是我们加上默认构造是可以的,说明,内部类和外部类是相对独立的

  • 内部类默认是外部类的友元函数(内部类的调用受到访问限定符的限制)

这里我们发现A类,突破类域就可以访问B,但是B不能说突破类域访问A

  • 如果你需要把外部类的构造给内部类使用,那么我们可以采取get成员函数的方式,或者静态成员变量的方式来进行使用

#include<iostream>
using namespace std;
class A
{
public:
	A(int a1 = 1, int a2 = 1) 
		:_a1(a1)
		,_a2(a2)
	{};
	int geta1()
	{
		return _a1;
	}
	class B
	{
	public:
		//直接访问类(这里没有默认构造)(可以接收参数)
		B(const A a)
			:_b1(a._a1)
			,_b2(a._a2)
		{}

		//默认构造写法
		B(int b1 = 2, int b2 = 2)
			:_b1(b1)
			,_b2(_b2)
		{}
	private:
		int _b1;
		int _b2;
	};
private:
	int _a1 = 1;
	int _a2 = 1;
};


int main()
{
	A a;
	int ret1 = a.geta1();
	A::B b = { ret1 };

	return 0;
}

内部类的使用2: 

没有学习之前:

这里我使用vs编译器,vs编译器不支持可边长数组,所以代码有点不一样

#include<iostream>
using namespace std;
//求1+2......+n//不能使用乘除
class sum
{
public:
	sum()
	{
		_ret += _i;
		++_i;
	}
	//获取ret最终的结果
	static int _GetRet()
	{
		return _ret;
	}
private:
	static int _i;
	static int _ret;
};
int sum::_i = 1;
int sum::_ret = 0;


class solution
{
public:
	int _solution(int n)
	{
		for (int i = 0; i < n; i++)
		{
			//创建n次构造函数,n次构造函数++会依次递加
			sum s;
		}
		//创建n次数之后,我们计算出来数值,此时我们可以选择数值来进行接收
		int ret = sum::_GetRet();
		//打印数值
		cout << ret << endl;

		//返回数值
		return sum::_GetRet();
	}
};

int main()
{
	solution s;
	int ret = s._solution(100);//这里接收进行验证,发现是正确的
	cout << ret << endl;//打印出来
	return 0;
}

sum

  1. 成员变量:

    • static int _i:静态成员变量,用于记录当前要累加的数字。初始化为 1。
    • static int _ret:静态成员变量,用于存储累加的结果。初始化为 0。
  2. 构造函数:

    • 每次创建 sum 类的对象时,构造函数被调用。在构造函数中,将当前的 _i 值累加到 _ret 中,然后将 _i 的值自增。这样,每次创建对象就相当于进行一次累加操作。
  3. 静态成员函数 _GetRet()

    • 用于获取 _ret 的值,即累加的结果。

solution

  1. 成员函数 _solution(int n)
    • 这个函数接受一个整数 n,目的是计算从 1 加到 n 的和。
    • 通过一个循环创建 n 次 sum 类的对象。每次创建对象时,sum 类的构造函数会自动进行累加操作。
    • 最后,通过 sum::_GetRet() 获取累加的结果,并将其赋值给 ret,然后打印和返回这个结果。

学习之后:

这里采取的是vs编译器,vs编译器是不支持可变长数组的,所以代码有点出入

#include<iostream>
using namespace std;
class sol
{
	//内部类
	class Sum
	{
	public:
		Sum()
		{
			_ret += _i;
			++_i;
		}

		static int _i;
		static int _ret;
	};

public:
	static int _sol(int n)
	{
		for (size_t i = 0; i < n; i++)
		{
			Sum s;
		}
        //这里不需要成员函数了,直接可以访问私有变量
		return Sum::_ret;
	}
};

//这里需要注意一下,因为我们需要突破类域
int sol::Sum::_i = 1;
int sol::Sum::_ret = 0;

int main()
{
	sol s;
	int ret = s._sol(100);
	cout << ret << endl;
	return 0;
}

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

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

相关文章

(02)python-opencv图像处理——更改颜色空间HSV

前言 1、更改颜色空间 1.1BGR 到 Gray 的示例 1.2 BGR 到 HSV 的示例&#xff1a; ​编辑 1.3 通过HSV进行颜色追踪 1.3.1hsv cv.cvtColor(frame, cv.COLOR_BGR2HSV) 1.3.2 BGR vs HSV&#xff1a; 1.3.3 为什么使用 HSV 颜色空间&#xff1f; 1.3.4 cv.inRange(hsv…

oracle-函数-instr()的妙用以及相似功能like

INSTR(C1,C2[,I[,J]]) 【功能】在一个字符串中搜索指定的字符,返回发现指定的字符的位置; 【说明】多字节符(汉字、全角符等)&#xff0c;按1个字符计算 【参数】 C1 被搜索的字符串 C2 希望搜索的字符串 I 搜索的开始位置,默认为1 J 第J次出现的位置,默认为1 【…

安全帽未佩戴预警系统 劳保防护用品穿戴监测系统 YOLO

在建筑、矿山、电力等高危行业中&#xff0c;工人面临着各种潜在的危险&#xff0c;如高空坠物、物体打击等。安全帽能够有效地分散和吸收冲击力&#xff0c;大大降低头部受伤的严重程度。一旦工人未正确佩戴安全帽&#xff0c;在遭遇危险时&#xff0c;头部将直接暴露在危险之…

Linux网络编程 -- 网络套接字预备与udp

本文主要介绍网络编程的相关知识&#xff0c;在正式介绍网络编程之前&#xff0c;我们得先了解一些前置的知识。 1、端口号 我们上网其实就是两种动作&#xff0c;一个是将远处的数据拉取到本地&#xff0c;另一个是把我们的数据发送给远端。其实大部分的网络通信行为都是用户…

基于springboot vue3 工商局商家管理系统设计与实现

博主介绍&#xff1a;专注于Java&#xff08;springboot ssm springcloud等开发框架&#xff09; vue .net php phython node.js uniapp小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作☆☆☆ 精彩专栏推荐订阅☆☆☆☆…

【公共祖先】二叉树专题

里面涉及多个plus题 前言1.二叉树的最近公共祖先2.二叉搜索树的最近公共祖先3.二叉树的最近公共祖先II4.二叉树的最近公共祖先III5.二叉树的最近公共祖先IV 前言 公共祖先这一类题目&#xff0c;难度不大&#xff0c;但是非常实用&#xff0c;也是面试问到概率比较大的一类题目…

夜间数据库IO负载飙升?MySQL批量删除操作引发的问题排查

目录 问题现象 问题分析 修改建议 总结 问题现象 近日&#xff0c;某用户反馈他们的MySQL数据库实例在凌晨时段会频繁出现IO负载急剧上升的情况&#xff0c;这种状态会持续一段时间&#xff0c;随后自行恢复正常。为了查明原因&#xff0c;该用户通过DBdoctor工具收集了相…

DLL中函数导出时的注意事项

1.使用.def文件导出函数 1.1示例代码:使用stdcall 关键字 和 extern "C" 关键字修饰 dll中函数 BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) {switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:case DLL_THREAD_ATT…

sahi密集检测的推理技巧

最近在做一些计数的项目&#xff0c;样本中存在一些非常密集的目标&#xff0c;如果混杂一起训练指标很难达到要求&#xff0c;所以考虑在训练时不加入密集目标&#xff0c;训练使用正常的样本&#xff0c;在推理时使用密集检测方案。 在高分辨率图像中检测小目标一直是一个技…

【Qt+Python项目构建】- 02 Qt creator 14.0 + PySide6 如何让图像控件的尺寸变化和窗口一致

前言&#xff1a;【这是个AI不会回答的问题】 Qt Creator 新的版本又发出了&#xff0c;Pyside6 有很多新功能。但是&#xff0c;一些传统的方法要被淘汰了。 一个经典的例子是&#xff1a; 我有个一个图像要显示在Form里面的图像控件上&#xff0c;OK&#xff0c; 我现在拖…

Unity实现自定义图集(一)

以下内容是根据Unity 2020.1.0f1版本进行编写的   Unity自带有图集工具,包括旧版的图集(设置PackingTag),以及新版的图集(生成SpriteAtlas)。一般来说,unity自带的图集系统已经够用了,但是实际使用上还是存在一些可优化的地方,例如加载到Canvas上的资源,打图集不能…

JVM(学习预热 - 走进Java)(持续更新迭代)

目录 一、彻底认识Java虚拟机 开创世纪&#xff1a;Sun Classic 开创世纪&#xff1a;Exact VM 武林霸主&#xff1a;HotSpot VM 移动端虚拟机&#xff1a;Mobile/Embedded VM “三大”其二&#xff1a;BEA JRockit/IBM J9 VM 软硬结合&#xff1a;BEA Liquid VM/Azul VM…

更新子节点的优化策略1:目标old节点的位置预测

更新子节点的优化策略1&#xff1a;目标old节点的位置预测&#xff1a; 如果 oldStartVnode 和 newStartVnode 是同一个节点&#xff0c;直接 patchVnode&#xff0c;同时 oldStartIdx、newStartIdx 索引都加 1&#xff08;向右移动&#xff09;如果 oldEndVnode 和 newEndVno…

PE结构之 重定位表

那么,我们找到了某个 需要修改的绝对地址 的RVA, 将这个RVA转换成FOA后,这个绝对地址是读DWORD ,还是QWORD? 就是说,32位和64位是否有区别? 实验: 找到重定位表的数据,并观察在内存中和文件中的区别 将引用dll的exe文件,设置一下基址 同时DLL文件的基址和EXE文件设置一样,并…

肝了4天,我用ChatTTS和LLM让deeplearning.ai课程说上流畅中文

以下是「 豆包MarsCode 体验官」优秀文章&#xff0c;作者X2046。 我们都知道外网上有很多优秀的视频教程平台&#xff0c;比如 Coursera 和 deeplearning.ai。尤其是后者&#xff0c;由吴恩达老师与OpenAI、Langchain、LlamaIndex、AutoGen等公司和作者合作&#xff0c;推出了…

Spring Cloud Netflix Hystrix 熔断器讲解和案例示范

在分布式微服务架构中&#xff0c;每个服务之间相互依赖&#xff0c;当某个服务出现故障或延迟时&#xff0c;如果没有有效的故障隔离机制&#xff0c;可能导致整个系统雪崩式的失败。Netflix Hystrix 作为一种熔断器模式&#xff0c;旨在通过隔离服务之间的调用&#xff0c;提…

通过移动访问控制增强数据中心安全性

在当今数据驱动的世界里&#xff0c;信息是新的黄金标准&#xff0c;数据中心安全已成为每个 IT 部门的首要任务。数据隐私和道德管理不再仅仅是最佳实践&#xff0c;而是法律要求。因此&#xff0c;风险比以往任何时候都要高。 然后是内部威胁问题。根据 IBM 的 《2024 年数据…

Python案例--copy复制

在Python编程中&#xff0c;数据的复制是一个常见且重要的操作&#xff0c;它涉及到赋值、浅拷贝和深拷贝三种不同的概念。正确理解这三种操作对于编写高效且正确的程序至关重要。本文将通过一个简单的Python示例&#xff0c;探讨这三种数据复制方式的区别及其应用场景&#xf…

数据结构 ——— 单链表oj题:环状链表(求出环的入口节点)

目录 题目要求 手搓一个简易带环链表 代码实现 题目要求 给定一个链表的头节点 head&#xff0c;返回链表开始入环的第一个节点&#xff0c;如果链表无环&#xff0c;则返回NULL 手搓一个简易带环链表 代码演示&#xff1a; struct ListNode* n1 (struct ListNode*)mal…

深度学习:循环神经网络—RNN的原理

传统神经网络存在的问题&#xff1f; 无法训练出具有顺序的数据。模型搭建时没有考虑数据上下之间的关系。 RNN神经网络 RNN&#xff08;Recurrent Neural Network&#xff0c;循环神经网络&#xff09;是一种专门用于处理序列数据的神经网络。在处理序列输入时具有记忆性…