[C++]类和对象(上)

news2024/9/19 10:32:31

我们在之前已经将C++的入门基础做了讲解,在本章我们将系统性的阐述C++中类和对象的基本定义和用法

1.类的定义

目录

1.类的定义

1.类定义的格式

2.访问限定符

 3.类域

2.实例化

1.实例化的概念

2.实例化的对象大小

3.this指针 

3.类的默认成员函数

1.构造函数

2.析构函数

3.拷贝构造函数


类(Class)是面向对象程序设计(OOP,Object-Oriented Programming)实现信息封装的基础。类是一种用户定义的引用数据类型,也称类类型。每个类包含数据说明和一组操作数据或传递消息的函数。类的实例称为对象。

1.类定义的格式

我们这里以栈Stack为例,创建一个名为Stack的类,再来实现其的基本用法

  • class为定义类的关键字,Stack为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。
  • 为了区分成员变量,⼀般习惯上成员变量会加⼀个特殊标识,如成员变量前面或者后面加_ 或者 m开头
  •  C++中struct也可以定义类,C++兼容C中struct的⽤法,同时struct升级成了类,明显的变化是
    struct中可以定义函数,但是在一般情况下,我们还是使用class定义类
  • 定义在类⾯的成员函数默认为inline,即内联函数

Stack类定义代码如下所示

class Stack
{
public:
	// 成员函数
	void Init(int n = 4)
	{
		array = (int*)malloc(sizeof(int) * n);
		if (nullptr == array)
		{
			perror("malloc申请空间失败");
			return;
		}
		capacity = n;
		top = 0;
	}
	void Push(int x)
	{
		// ...扩容
		array[top++] = x;
	}
	int Top()
	{
		assert(top > 0);
		return array[top - 1];
	}
	void Destroy()
	{
		free(array);
		array = nullptr;
		top = capacity = 0;
	}
private:
	// 成员变量
	int* array;
	size_t capacity;
	size_t top;
}; // 分号不能省略

2.访问限定符

  • C++⼀种实现封装的方式,用类将对象的属性与方法结合在⼀块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
  • public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访问,protected和private是⼀样的,在继承中才会体现他们的区别
  • 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止,如果后面没有访问限定符,作用域就到 }即类结束。
  • class定义成员没有被访问限定符修饰时默认为private,struct默认为public。成员变量一般都会设置为private和 protected,除非你想将成员变量公开出去就使用public

 3.类域

作用域我们在之前的入门章节讲过,函数作用域,命名空间域,局部作用域,还有就是类域

类定义了⼀个新的作用域,类的所有成员都在类的作用域中,在类体外定义成员时,需要使用 :: 作
用域操作符指明成员属于哪个类域。 

在域外访问需要加域操作符::

2.实例化

1.实例化的概念

用类类型在物理内存中创建对象的过程,称为类实例化出对象

所以说,类只是一个模型,是用来创建对象的模型,类中的成员变量和成员函数只是声明,并没有实际的分配内存,只有当实例化成为了对象,才会分配内存空间

2.实例化的对象大小

如图所示,被同一个类所实例化的对象,由于他们的成员变量不同,因此会分配到不同的空间中去,但是他们所有的成员函数都是一样的,因此如果在为类成员函数单独分配空间就有点冗余了,不如将其存到公共代码区内,谁需要调用了直接去公共区域调用即可,互不影响。

类和C语言中的结构体一样,都具有内存对齐规则,而且规则一致

  • 第⼀个成员在与结构体偏移量为0的地址处。
  •  其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
  • 注意:对齐数 = 编译器默认的⼀个对齐数 与 该成员大小的较小值。
  •  VS中默认的对齐数为8
  • 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
  • 如果嵌套了结构体的情况,嵌套的结构体对其到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。 

3.this指针 

编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this
指针,当成员变量调用函数时,会隐式的传入this指针,this指针指向自己 

//这是编译器中的函数声明
void Init(Date* const this, int year,int month, int day)
//这是我们看到的函数声明
void Init(int year,int month, int day)

类的成员函数中访问成员变量,本质都是通过this指针访问的

C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显示使用this指针

3.类的默认成员函数

默认成员函数就是用户没有显式实现,编译器会自动生成的成员函数称为默认成员函数。⼀个类,我们不写的情况下编译器会默认生成以下6个默认成员函数,需要注意的是这6个中最重要的是前4个,最后两个取地址重载不重要,我们稍微了解⼀下即可。

1.构造函数

构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象(我们常使用的局部对象是栈帧创建时,空间就开好了),而是对象实例化时始化对象。即完成对类对象的初始化。

构造函数的特点:

  1.  函数名与类名相同。
  2. 无返回值。 (返回值啥都不需要给,也不需要写void,不要纠结,C++规定如此)
  3. 对象实例化时系统会自动调用对应的构造函数。
  4. 构造函数可以重载。
  5.  如果类中没有显式定义构造函数,则C++编译器会⾃动⽣成⼀个无参的默认构造函数,⼀旦用户显式定义编译器将不再生成。
  6. 无参构造函数、全缺省构造函数、我们不写构造时编译器默认生成的构造函数,都叫做默认构造函数。但是这三个函数有且只有⼀个存在,不能同时存在。实际上无参构造函数、全缺省构造函数也是默认构造,总结⼀下就是不传实参就可以调用的构造就叫默认构造

 我们看一下日期类的几个构造函数

class Date
{
public:
	// 1.⽆参构造函数
	Date()
	{
		_year = 1;
		_month = 1;
		_day = 1;
	}
	// 2.带参构造函数
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	// 3.全缺省构造函数
	/*Date(int year = 1, int month = 1, int day = 1)
	{
	_year = year;
	_month = month;
	_day = day;
	}*/
private:
	int _year;
	int _month;
	int _day;
};

2.析构函数

析构函数与构造函数功能相反,析构函数不是完成对对象本身的销毁,比如局部对象是存在栈帧的,函数结束栈帧销毁,他就释放了,不需要我们管,C++规定对象在销毁时会自动调用析构函数,完成对象中资源的清理释放工作。 

析构函数的特点:

  1. 析构函数名是在类名前加上字符 ~。
  2.  无参数无返回值。 (这⾥跟构造类似,也不需要加void)
  3. ⼀个类只能有⼀个析构函数。若未显式定义,系统会自动生成默认的析构函数。
  4. 对象生命周期结束时,系统会自动调用析构函数。
  5. 跟构造函数类似,我们不写编译器自动生成的析构函数对内置类型成员不做处理,自定类型成员会调用他的析构函数。
  6. 还需要注意的是我们显示写析构函数,对于自定义类型成员也会调用他的析构,也就是说自定义类型成员无论什么情况都会自动调用析构函数。
  7. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,如Date;如果默认生成的析构就可以用,也就不需要显示写析构,如MyQueue;但是有资源申请时,⼀定要自己写析构,否则会造成资源泄漏,如Stack。
  8. ⼀个局部域的多个对象,C++规定后定义的先析构

看一下栈对象的析构函数

~Stack()
{
cout << "~Stack()" << endl;
free(_a);
_a = nullptr;
_top = _capacity = 0;
}

3.拷贝构造函数

如果⼀个构造函数的第一个参数是自身类类型的引用,且任何额外的参数都有默认值,则此构造函数也叫做拷贝构造函数,也就是说拷贝构造是⼀个特殊的构造函数。

1. 拷贝构造函数是构造函数的⼀个重载。
2. 拷贝构造函数的参数只有⼀个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为语法逻辑上会引发无穷递归调用


3. C++规定自定义类型对象进行拷贝行为必须调用拷贝构造,所以这里自定义类型传值传参和传值返回都会调用拷贝构造完成。
4. 若未显式定义拷贝构造,编译器会自动生成拷贝构造函数。自动生成的拷贝构造对内置类型成员变量会完成值拷贝/浅拷贝(⼀个字节⼀个字节的拷贝),对自定义类型成员变量会调用他的拷构

5.传值返回会产生⼀个临时对象调用拷贝构造,传值引用返回,返回的是返回对象的别名(引用)没
有产生拷贝。但是如果返回对象是⼀个当前函数局部域的局部对象,函数结束就销毁了,那么使用
引用返回是有问题的,这时的引用相当于⼀个野引用,类似⼀个野指针⼀样。传引用返回可以减少
拷贝,但是⼀定要确保返回对象,在当前函数结束后还在,才能用引用返回。

以上是对类和对象的上半部分阐述与讲解

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

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

相关文章

二、Kubernetes中pod的管理及优化

目录 一 kubernetes 中的资源 1.1 资源管理介绍 1.2 资源管理方式 1.2.1 命令式对象管理 1.2.2 资源类型 1.2.3 基本命令示例 1.2.4 运行和调试命令示例 1.2.5 高级命令示例 二 什么是pod 2.1 创建自主式pod &#xff08;生产不推荐&#xff09; 2.2 利用控制器管理…

CPLEX+Yalmip+MATLAB2022a配置

来源&#xff1a;yalmipcplex12.10文件及安装教程-CSDN博客https://blog.csdn.net/qq_41944352/article/details/126421198 安装包 来源&#xff1a;yalmipcplex12.10文件及安装教程-CSDN博客 Cplex 需下载&#xff1a; Microsoft Visual C 2015 Redistributable 添加路径&a…

时空大数据平台:激活新质生产力的智慧引擎

在数字化转型的浪潮中&#xff0c;时空大数据平台以其独特的价值&#xff0c;成为推动新质生产力发展的关键力量。本文不仅深入剖析时空大数据平台的定义与内涵&#xff0c;探讨其在智慧城市、智慧农业、环境管理、应急管理等领域的应用成效&#xff0c;还将详尽阐述平台如何通…

【C++】unordered系列

前言&#xff1a; 在C11及以后的标准中&#xff0c;unordered容器是标准模板库&#xff08;STL&#xff09;的一部分&#xff0c;提供了高效的数据结构选项&#xff0c;适用于需要快速查找和插入操作的场景。 unordered通常与关联容器一起使用&#xff0c;特别是unordered_map和…

【ESP32】ESP-IDF开发 | GPIO通用输入输出+LED点灯和按键输入例程

1. 简介 ESP32芯片有34个物理GPIO pad&#xff0c;每个GPIO pad都可用作一个通用IO或连接一个内部的外设信号。IO_MUX、RTC IO_MUX和GPIO交换矩阵用于将信号从外设传输至GPIO pad。 从上面看到&#xff0c;每个pad可以配置成GPIO功能&#xff08;连接GPIO交换矩阵&#xff09;或…

7-17 汉诺塔的非递归实现

输入样例: 3输出样例: a -> c a -> b c -> b a -> c b -> a b -> c a -> c 分析&#xff1a; 不会汉罗塔的uu们&#xff0c;先看看图解&#xff1a; 非递归代码&#xff1a; #include<iostream> #include<stack> using namespace std; s…

tomcat的Catalinalog和localhostlog乱码

找到tomcat安装目录的loging文件 乱码这两个由UTF-8改为GBK

C++笔记---多态

1. 多态的概念 多态(polymorphism)的概念&#xff1a;通俗来说&#xff0c;就是多种形态。 多态分为编译时多态(静态多态)和运行时多态(动态多态)&#xff0c;这里我们重点讲运行时多态&#xff0c;编译时多态(静态多态)和运行时多态(动态多态)。 编译时多态(静态多态)主要就…

MySQL中定义空值

如果一行中的某个列缺少数据值&#xff0c;该值被置为null&#xff0c;或者说包含一个空。 空是一个难以获得的、未分配的、未知的&#xff0c;或不适用的值。空和0或者空格不相同。0是一个数字&#xff0c;而空格是一个字符。 算术表达式中的空值 示例&#xff1a;计算年薪包…

CSS 布局技巧实现元素左右排列

开发中经常会遇到一个场景&#xff0c;使用 CSS 实现一个子元素靠右&#xff0c;其余子元素靠左。 这里总结一下常见的实现方式。 1. flex 布局 flexbox 是一种常用且灵活的布局方式&#xff0c;适合完成这种需求。将父容器设置为 display: flex&#xff0c;然后使用 margin…

Matlab Simulink 主时间步(major time step)、子时间步(minor time step)

高亮颜色说明&#xff1a;突出重点 个人觉得&#xff0c;&#xff1a;待核准个人观点是否有误 高亮颜色超链接 文章目录 对Simulink 时间步的理解Simulink 采样时间的类型Discrete Sample Times(离散采样时间)Controllable Sample Time(可控采样时间) Continuous Sample Times(…

51单片机-系列-单片机基础知识入门流水灯

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 单片机基础知识入门 常用的单片机封装 DIP直插 在DIP直插中&#xff0c;我们根据引脚数量的不同分为8P,14P,16P,18P,20P&#xff0c;这些是窄体&#xff0c;除了窄体之外&…

调用百度翻译API遇到的跨域问题解决方案

&#x1f389; 前言 这几天在学习前端的时候需要写一个实例&#xff0c;是关于翻译功能的。于是便想着在网上找一些API看能不能调用。这里遇到一个很坑的问题&#xff0c;就是我在暑假学习的时候曾经调用过心知天气的API、QQ音乐的API和今日头条的API&#xff0c;都未曾遇到过…

RT-DETR改进策略:BackBone改进|Swin Transformer,最强主干改进RT-DETR

摘要 在深度学习与计算机视觉领域,Swin Transformer作为一种强大的视觉Transformer架构,以其卓越的特征提取能力和自注意力机制,正逐步引领着图像识别与检测技术的革新。近期,我们成功地将Swin Transformer引入并深度整合至RT-DERT(一种高效的实时目标检测与识别框架)中…

BSV区块链上的覆盖网络服务现已开放公测

​​发表时间&#xff1a;2024年8月30日 BSV区块链的覆盖网络服务现已正式开放公测。对于BSV区块链生态系统内的特定交易类型和数据管理及访问&#xff0c;覆盖网络服务都可以为它们提供强大、可扩展、并且合规的解决方案。覆盖网络以及其它即将推出的BSV服务将赋予开发者、企业…

文件误删除?助你一键恢复

文件误删除之痛 在日常的数字生活中&#xff0c;文件误删除是许多用户不时会遭遇的“小确丧”。无论是手滑点击了“删除”键&#xff0c;还是系统崩溃导致的文件丢失&#xff0c;这些意外事件总能让人心急如焚。文件误删除不仅可能意味着重要资料的永久消失&#xff0c;还可能…

Linux驱动编程 - platform平台设备驱动总线

目录 简介&#xff1a; 一、初识platform平台设备驱动 1、platform_driver驱动代码框架 2、platform_device设备代码框架 3、测试结果 3.1 Makefile编译 3.2 加载驱动 二、platform框架分析 1、注册platform总线 1.1 创建platform平台总线函数调用流程 1.2 platform_b…

鸿蒙开发之ArkTS 基础三 数组

数组可以存储多个数据 语法为: let 数组名字:数组类型[] [数据一,数据二 ,数据三 ,数据四 ,数据5⃣️] 例如:学生类数组 let students:string[] [小美,小红,小张,小西] console.log("students",students) 输出 小美,小红,小张,小西 这里不需要遍历就能输出内容…

C Primer Plus 第5章习题

你该逆袭了 红色标注的是&#xff1a;错误的答案 蓝色标注的是&#xff1a;正确的答案 绿色标注的是&#xff1a;做题时有疑问的地方 橙色标注的是&#xff1a;答案中需要着重注意的地方 练习题 一、复习题1、2、3、4、错误答案&#xff1a;正确答案&#xff1a; 5、我的答案&a…

十三,Spring Boot 中注入 Servlet,Filter,Listener

十三&#xff0c;Spring Boot 中注入 Servlet&#xff0c;Filter&#xff0c;Listener 文章目录 十三&#xff0c;Spring Boot 中注入 Servlet&#xff0c;Filter&#xff0c;Listener1. 基本介绍2. 第一种方式&#xff1a;使用注解方式注入&#xff1a;Servlet&#xff0c;Fil…