【C++从入门到放弃】类和对象(上)

news2024/11/24 5:35:55

🧑‍💻作者: @情话0.0
📝专栏:《C++从入门到放弃》
👦个人简介:一名双非编程菜鸟,在这里分享自己的编程学习笔记,欢迎大家的指正与点赞,谢谢!

在这里插入图片描述

类和对象(上)

  • 前言
  • 一、类的引入
  • 二、类的定义
  • 三、类的访问限定符及封装
    • 1. 访问限定符
    • 2. 封装
  • 四、类的作用域
  • 五、类的实例化
  • 六、类对象模型
    • 1. 计算类对象的大小
    • 2. 结构体内存对齐规则
  • 七、this指针
    • 1. 什么是this指针
    • 2. this指针的特性
  • 总结


前言

  在学习类和对象之前,我们要对面向过程和面向对象有一个初步的了解:C语言是面向过程的,面向过程所关注的是分析出解决问题的步骤,通过函数调用逐步解决问题;C++是面向对象的,面向对象是把构成问题事务分解成多个不同的对象,靠对象之间的交互完成,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。


一、类的引入

  C语言中,结构体内部只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。

typedef int DataType;
struct Stack
{
	void Init(size_t capacity)
	{
		_array = (DataType*)malloc(sizeof(DataType) * capacity);
		if (nullptr == _array)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = capacity;
		_size = 0;
	}
	void Push(const DataType& data)
	{
		// 扩容
		_array[_size] = data;
		++_size;
	}
	DataType Top()
	 {
		return _array[_size - 1];
	}
	void Destroy()
	{
		if (_array)
		{
			free(_array);
			_array = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}
	DataType* _array;
	size_t _capacity;
	size_t _size;
};

int main()
{
	Stack s;
	s.Init(10);
	s.Push(1);
	s.Push(2);
	s.Push(3);
	cout << s.Top() << endl;
	s.Destroy();
	return 0;
}

  可以看到,在这个结构体内,我们不仅定义了变量,而且还定义了函数,这也是C语言和C++的区别之一,但是在C++里,通常不会称其结构体,而是类,是一个Stack类。在C++中,通常使用class来代替struct。

二、类的定义

class className
{
	// 类体:由成员函数和成员变量组成
};  // 一定要注意后面的分号

  class为定义类的关键字ClassName类的名字{}中为类的主体,注意类定义结束时后面分号不能省略。
  类体中内容称为类的成员:类中的变量称为类的属性成员变量; 类中的函数称为类的方法或者成员函数

类的两种定义方式:

  1. 声明和定义全部放在类体中,成员函数如果在类中定义,编译器可能会将其当成内联函数处理。这种定义方式和上面的例子类似。
  2. 类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::
//声明放在类的头文件(Date.h)当中
class Date
{
public:
	void PrintDate();

	int _year;
	int _month;
	int _day;	
};
定义放在类的实现文件(.cpp)当中
#include "Date.h"
void Date::PrintDate()
{
	cout<<_year<<"年"<<_month<<"月"<<_day<<"日"<<endl;
}

三、类的访问限定符及封装

1. 访问限定符

  C++实现封装的方式:通过类将对象的属性(变量)与方法(函数)结合在一块,让对象更加完善,更加整体,通过访问权限选择性的将其接口提供给外部的用户使用。

访问限定符共有三个:public(公有)、protected(保护)、private(私有)

  1. public修饰的成员在类外可以直接被访问
  2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
  3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
  4. 如果一个访问限定符后面再没有访问限定符,访问权限作用域从该访问限定符就到 } 即类结束。
  5. class的默认访问权限为private,struct为public(因为struct要兼容C)

注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别

2. 封装

  封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

  封装本质上是一种管理,让用户更方便使用类。举个简单例子来说:你要去银行存钱,你只需要在规定的窗口办理业务就行,和你进行交互的只是柜台的银行人员而已,你不需要去管你的钱银行会怎么存,会存到哪里,银行内部的存钱细节、流程都会被封装起来,仅仅对你只开放了一个窗口。
  在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用

四、类的作用域

  类定义了一个作用域,类中的所有成员都在这一个作用域当中。当在类外要定义成员时,需要使用 :: 作用域操作符来指明该成员是属于那个类域当中的。
  就比如在上面的代码当中,要在 Date 类外定义一个 PrintDate 函数时就得指明该函数是属于哪个类域当中的。

五、类的实例化

  用类类型创建对象的过程,称为类的实例化(类定义)

  1. 类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它;比如:入学时填写的学生信息表,表格就可以看成是一个类,来描述具体学生信息。
  2. 一个类可以实例化出多个对象,这就相当于有一张设计图纸,但是可以按照图纸建造多个房子一样,实例化出的对象 占用实际的物理空间,存储类成员变量。
  3. 类实例化出对象这个过程就类似于使用建筑设计图建造出房子,类就像是设计图,它只有一个框架,并没有实际的内存数据,只有当通过使用图纸建造出房子才算实例化,实例化出的对象才能实际存储数据,占用物理空间。

在这里插入图片描述

六、类对象模型

1. 计算类对象的大小

class Date
{
public:
	void PrintDate()
	{
		cout<<_year<<"年"<<_month<<"月"<<_day<<"日"<<endl;
	}
private:
	int _year;
	int _month;
	int _day;	
};

  可以看到,在一个类中,既有成员变量,又有成员函数,肯定的是变量是占内存空间的,但是函数占不占空间呢?如果占会占多大呢?

  当使用 sizeof() 计算类对象大小时会发现类对象的大小只有成员变量,不包括成员函数,并且还要注意内存对齐原则。上面的对象大小就是12个字节。
  这也就是为什么成员变量在对象当中,而成员函数不在对象当中。再对这句话做一个解释,当实例化出一个对象,它对应的变量肯定是各自对象所拥有的,但是对于成员函数来说,就没有必要给每一个对象都配备一份相同的代码,多个对象使用同一个函数也是没有问题的。举个例子,对象就相当于人,而函数可比作为一个篮球场,没有必要给没一个都建一个篮球场,只需要建一个大家一块使用就可以。而这些函数代码会放在公共区域(代码段),要使用该函数时就去公共区间调用。

注意:当类没有成员变量或者是一个空类时会有多大呢?

在经过测试发现会有一个字节的内存,而这一字节的内存仅仅是用来占位,标识对象被定义出来了。

2. 结构体内存对齐规则

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

七、this指针

1. 什么是this指针

class Date
{ 
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout <<_year<< "-" <<_month << "-"<< _day <<endl;
	}
private:
	int _year;     // 年
	int _month;    // 月
	int _day;      // 日
};

int main()
{
	Date d1, d2;
	d1.Init(2000,1,1);
	d2.Init(2023,2,26);
	d1.Print();
	d2.Print();
	return 0;
}

  可以看到,在Date类中有 Init 与 Print 两个成员函数,当时我们 d1 对象调用 Init 函数时,我们会觉得将日期分别赋值给了 _year、_month、_day,可是再当 d2 对象调用该函数时同样也把 d2 对象的日期分别给到了 _year、_month、_day,难道这样不会发生值替换吗?

  C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

void Init(int year, int month, int day)
{
	this->_year = year;
	this->_month = month;
	this->_day = day;
}

2. this指针的特性

  1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值
  2. 只能在“成员函数”的内部使用
  3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针,this指针存在于栈中。
  4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递

总结

以上都是我自己对学习类和对象的简单认识,当然对类和对象的学习还没有结束,后面还有更多的知识等待着自己,相信拥有了这些知识可以让自己进一步地去学习C++的知识。

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

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

相关文章

JavaScript 高级1 :面向对象

JavaScript 高级1 &#xff1a;面向对象 Date: January 16, 2023 Text: 面向对象、ES6中类和对象、类的继承、面向对象案例 目标&#xff1a; 能够说出什么是面向对象 能够说出类和对象的关系 能够使用 class 创建自定义类型 能够说出什么是继承 面向对象编程介绍 面向过…

JDK安装指导

Oracle官网地址https://www.oracle.com/java版本查询这里仅标识了java19和java17java archived 查看更多随便进入一个&#xff0c;根据后缀提示下载对应包即可Linux安装&#xff08;示例 java 1.8版本&#xff09;https://www.oracle.com/java/technologies/javase/javase8u211…

基于MaixBit(K210芯片)的图像识别猜拳手势博弈装置

本文介绍了一种基于嵌入式平台开发的图像识别部署装置&#xff0c;其主要功能包括实现机器与人的“猜拳博弈”&#xff0c;其组成分为三个部分&#xff1a;手势检测数据集图像识别模型训练模型格式部署maixbit开发板部署手势检测数据集&#xff1a;本项目的数据集包括三种标签&…

2023自动化测试岗位需求的 7 项必备技能 (最新版)

目录&#xff1a;导读 一、自动化测试员技能——编程语言 二、自动化测试员技能–出色的手动测试技能 三、.自动化测试员技能–自动化工具专业知识 四、自动化测试员技能–了解业务需求 五、自动化测试员技能–自动化工具故障排除 六、自动化测试员技能–具有测试管理工具…

Android 网络框架——Retrofit源码精析

众所周知&#xff0c;Retrofit是OkHttp的封装&#xff0c;APP对网络交互部分的实现基本上都是RxJavaRetrofitOkHttp架构&#xff08;或协程RetrofitOkHttp&#xff09;&#xff0c;可以说&#xff0c;Retrofit已经广为人知。本文主要介绍Retrofit主线源码实现机制&#xff0c;及…

二叉树的前序遍历-java两种方式-力扣144

一、题目描述给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。示例 1&#xff1a;输入&#xff1a;root [1,null,2,3]输出&#xff1a;[1,2,3]示例 2&#xff1a;输入&#xff1a;root []输出&#xff1a;[]示例 3&#xff1a;输入&#xff1a;root [1]输出…

MySQL进阶(二)

目录 1、视图 1、检查选项 2、视图的更新 3、视图作用 2、存储过程 1、语法 2、变量 1、系统变量 2、用户定义变量 3、局部变量 3、if 4、参数 5、case 6、循环 1、while 2、repeat 3、loop 7、游标、条件处理程序 8、存储函数 3、触发器 4、锁 1、全局锁 2、表级锁 …

AIR系列|板载LED|gpio引脚选择|GPIO|流水灯|LuatOS-SOC接口|官方demo|学习(20-1):GPIO库基础

AIR系列各型号开发板板载LED对应管脚及GPIO控制代码 AIR103&#xff1a; rtos_bsp "AIR103" then -- Air103开发板LED引脚编号--return pin.PB26, pin.PB25, pin.PB24return 42,41,40 AIR105&#xff1a; rtos_bsp "AIR105" then -- Air105开发板LED引…

DFT基本入门介绍

1.什么是DFT&#xff1f;2.为什么要做DFT&#xff1f;3.“测试”与“验证”的区别4.DFT的核心技术1&#xff09;扫描路径设计&#xff08;Scan Design&#xff09;2)内建自测试&#xff08;Bist&#xff09;3)JTAG4)ATPG5.DFT工程师的岗位职责随着芯片的制程越来小(5nm), 芯片的…

xxjob分布式任务调度

前言 在工作中使用到了定时任务,通过查找资料选择了xxjob,以下是xxjob的介绍以及基本的使用. xxjob介绍 XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。 将调度行为抽象形成“调度中心”公共平台&#xff0c;而平台自身…

vue3+rust个人博客建站日记3-编写主页

内容 绘制了主页的基本布局设置了封装了header栏组件并设置了全局黑夜模式. 选择一个组件库-Naive UI 如果没有设计能力&#xff0c;又想开发出风格统一的前端页面。就一定要选择一个漂亮的组件库。 本次项目选择使用Naive UI&#xff0c;NaivUI库曾被Vue框架作者尤雨溪推荐…

【云原生】k8s核心技术—集群安全机制 Ingress Helm 持久化存储-20230222

文章目录一、k8s集群安全机制1. 概述2. RBAC——基于角色的访问控制二、Ingress三、Helm1. 引入2. 使用功能Helm可以解决哪些问题3. 介绍4. 3个重要概念5. helm 版本变化6. helm安装及配置仓库7. 使用helm快速部署应用8. 自己创建chart9. 实现yaml高效复用四、持久化存储1.nfs—…

ArXiv简介以及论文提交

arXiv网站简介 arXiv是一个收集物理学、数学、计算机科学、生物学与数理经济学的论文预印本的网站。其中arXiv发音同“archive”&#xff0c;因为“X”代表希腊字母 &#xff0c;国际音标为[kai]。它于1991年8月14日成立&#xff0c;现由美国康奈尔大学维护。 ——维基百科 对…

在Angular项目中引入NG-ZORRO

在Angular项目中引入NG-ZORRO1.前置2.安装NG-ZORRO并进行初始化配置3.引入样式4.引入组件1.前置 首先创建一个angular项目&#xff1a;angular创建一个新项目的步骤 这是我项目的结构&#xff1a; 2.安装NG-ZORRO并进行初始化配置 安装NG-ZORRO&#xff1a;cd 到当前项目位…

微信小程序、小游戏的流量主一般可以赚多少钱?

本篇文章主要科普小程序、小游戏流量主一般赚钱的实际情况&#xff0c;通过在下长期运营的经验汇总而成。 日期&#xff1a;2023年2月26日 作者&#xff1a;任聪聪 小程序、小程序满1000用户后即可开通流量主&#xff0c;但实际上很多人并没有传说中的那种日赚几千的流量收入的…

学习笔记之Vuex(五)

Vuex&#xff08;五&#xff09;Vuex一、什么是Vuex二、Vuex工作原理三、搭建Vuex环境四、求和案例分析4.1 求和案例——vue实现4.2 求和案例——vuex实现&#xff08;五&#xff09;Vuex 一、什么是Vuex 1.概念 在Vue中实现集中式状态&#xff08;数据&#xff09;管理的一…

第二节类型转换、运算符

类型转换 自动类型转换&#xff1a; 类型小的变量可以赋值给大的类型变量。 表达式的自动类型转换&#xff1a; byte short char在表达式中是当做 int计算的。 强制类型转换&#xff1a; 大类型的变量转化为小类型的变量。 注&#xff1a;浮点型转换为整数是直接丢掉小数部…

nacos config

https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-config 必须在 bootstrap.properties 配置 nacos server 的地址 data id : 对应一个微服务 namespace : 对应环境 dev prod 默认 public group : 对应一个项目&#xff0c;&#xff0c;默认 DEFUALT_GROUP 当你…

神经网络 线性回归从0开始实现的代码分析 --跟李沐学AI

3.2. 线性回归的从零开始实现 — 动手学深度学习 2.0.0 documentation 分析了好几天才懂,个人水平有限 如果有错请指出 1.导包 %matplotlib inline import random import torch from d2l import torch as d2ldef synthetic_data(w, b, num_examples): #save""&quo…

spring integration使用:消息转换器

系列文章目录 …TODO spring integration开篇&#xff1a;说明 …TODO spring integration使用&#xff1a;消息路由 spring integration使用&#xff1a;消息转换器 spring integration使用&#xff1a;消息转换器系列文章目录前言消息转换器&#xff08;或者叫翻译器&#x…