C++基础(2)——类和对象

news2024/11/17 5:29:47

目录

1. 类的引入:

2. 类的定义:

2.1类的定义以及基本结构:

2.2 类的访问限定符:

3. 类的声明与定义的分离:

4. 类的实例化:

5. 类的大小计算:


1. 类的引入:

      在数据结构系列的文章中,经常会使用结构体来构建例如顺序表,链表等数据结构的大体结构。在C语言中,结构体内部只能定义变量。但是在C++中,对结构体进行了修改,称之为类,类中不但可以定义变量,也可以定义函数。同时,类也兼容了C语言中结构体的所有用法。为了具体体现两种语言中结构体的不同,下面将通过一个示例进行解释:

     在数据结构的栈这一部分中,对于栈这一数据结构的定义可以由下面的代码表示:

struct Stack
{
	int* a;
	int top;
	int capacity;
};

void StackInit(struct Stack* ps);

void StackPush(struct Stack* ps, int x);

(注:此处只简单的引入栈的基本结构以及部分功能函数的声明,用于解释类和结构体的不同)

    在C语言中,如果不对结构体进行typedef来重命名,则在使用时,必须带上struct。在C++中,对这部分进行了优化,在使用结构体时,只需要结构体名即可。例如对于上述代码,在C语言中,如果想要使用结构体,需输入

struct Stack S1;

而在C++中使用时,类名即类型,不需要加上struct。即:

Stack S1;

      上面提到了,在C++中,类(结构体)中可以定义函数,如果将开头关于栈的相关代码利用C++进行修改,可以很好的简化代码书写,即:

struct Stack
{
	int* a;
	int top;
	int capacity;

	void Init();

	void Push(int x);
};

        从上面给出的代码不难看出,利用C++对栈的相关代码进行改写时,不但让函数中的参数数量减少,并且还化简了C语言中与栈相关的功能函数的函数名。例如向栈中插入元素,C语言中此函数的函数名为StackPush,在C++中为Push。这是因为在C语言中,由于结构体内部不能定义函数,并且对于其他种类的数据结构中,均有初始化函数Init。如果不在函数名之前加上不同种类数据结构的名字加以区分,并且在C语言中并不存在函数重载。会造成错误。

       而在C++中,因为类的作用域(对于类的作用域将在文章后部给予相关解释,本处只是提出这个概念关系,并且可以在类中定义函数,因此,可以在不同的类中,同时定义Init

2. 类的定义:

2.1类的定义以及基本结构:

      上面给出了定义类的一个方法,即利用struct,本部分给出另一个用于定义类的关键字class,具体结构如下:

class className
{
// 类体:由成员函数和成员变量组成
}; 

       其中,class为定义类的关键字,ClassName为类的名字,{}{}中为类的主体,类主体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。

2.2 类的访问限定符:

  对于类的访问限定符,为public,protected,private

三者之间的区别为,public修饰的成员变量可以在类外访问。而protected,private修饰的成员变量只能在类中被访问。

对于三个访问限定符的作用权限,可分为下面两种情况:

    1.如果任意访问限定符(例如下面给出代码中访问限定符private)后面的代码中存在其他的访问限定符(例如下面代码中的public),则private的作用权限在遇到public后截止。例如:

class Stack
{
	private:
		int* a;
		int top;
		int capacity;

    public:
	void Init();

	void Push(int x);
};

     2.如果任意的访问限定符(例如下面代码中的public)中截止到类的"}"之前没有其他的访问限定符,则public的访问权限作用截止到类的末尾。例如:

class Stack
{
	private:
		int* a;
		int top;
		int capacity;

    public:
	void Init();

	void Push(int x);
};

  对于struct,class这两个关键字都可以来定义类。二者的不同主要体现在默认的访问权限上,对于struct,其默认的访问权限为public。对于class,其默认的访问权限为private

3. 类的声明与定义的分离:

     在之前数据结构的章节中,经常会让函数的声明和定义分离在两个文件中,对于类而言,加入在类中给出一个函数的声明,在外部给出函数的定义,方法如下:

void Stack::Init()
{
	a = 0;
	top = 0;
	capacity = 0;
}

  除了上述情况,如果将函数的声明与定义同时放在类中,会出现两种情况:

1. 函数的代码行数较少,此时函数会自动变为内联函数。

2. 函数的代码行数较多,函数不会变成内联函数。

class Stack
{
	private:
		int* a;
		int top;
		int capacity;

    public:
		void Init();

		void Push(int x)
		{
			a[top] = x;
			capacity++;
			top++;
	    }
};

       因此,对于较为短小的函数,适合之间定义在类中,而较为复杂的函数适合采用声明与定义分离的方法。

4. 类的实例化:

  定义如下:用类类型创建对象的过程,称为类的实例化。类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类,并没有分配实际的内存空间来存储它。例如:

class Stack
{
public:
	int _year;
	int _month;
	int _day;
};

        在类中给出上面三个变量,需要注意,类中的变量,只是变量的声明,这种变量并没有在内存中开辟空间,在没有进行类的实例化的情况下,并不能进行使用,例如:

int main()
{

	Stack::_day = 2023;

	return 0;
}

        如果运行上述给出的代码,编译器会显示报错。这是因为此时的变量day只是一个声明,并没有在内存中开辟空间。

      如果想要使用上述变量,首先需要进行一次类的实例化,代码如下:

int main()
{

	Stack Time; //实例化
	Time._day = 12;
	Time._month = 11;
	Time._year = 2023;

	return 0;
}

5. 类的大小计算:

例如对于下面给出的类:

class Stack1
{
	void Push(int x)
	{
		
	}

public:
	int _year;
	int _month;
	int _day;
};

class Stack2
{


public:
	int _year;
	int _month;
	int _day;
};

      不难发现,上述代码给出的两个类中,不同点为Stack1中包含了一个函数,Stack2中只声明了三个整型变量。通过下面的代码打印其大小:
 

int main()
{
	Stack1 time;
	Stack2 time1;

	cout << sizeof(time) << endl;
	cout << sizeof(time1) << endl;
	return 0;
}

结果如下:

       不难发现,二者大小的值是相同的,也就是说,计算类的大小时,并没有将类中的函数计算在内。这是因为,在每次调用时,类中的变量都会接收不同的值,而函数除了传递的形式参数没有任何变化,因此,在类中,变量是独立存储的,而函数,则是在一个公共空间中存储的。

       如果将上述的类进行部分更改,即:

class Stack3
{


public:
	char _year;
	int _month;
	int _day;
};

 此时打印结果为:

通过打印结果不难发现,类中变量的存储依旧满足内存对齐原则,即:

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

在类的大小这部分,还有一个特殊的例子,即空类:

class Stack4
{

};

当打印空类的大小时,即:
 

int main()
{
	Stack4 a;

	cout << sizeof(a) << endl;
	return 0;
}

结果如下:

因此,对于上述无成员变量的类的对象(a),大小为1字节。这1字节并不存储有效数字,仅用来表示定义的对象(a)存在。

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

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

相关文章

有源RS低通滤波

常用的滤波电路有无源滤波和有源滤波两大类。若滤波电路元件仅由无源元件&#xff08;电阻、电容、电感&#xff09;组成&#xff0c;则称为无源滤波电路。无源滤波的主要形式有电容滤波、电感滤波和复式滤波(包括倒L型、LC滤波、LCπ型滤波和RCπ型滤波等)。若滤波电路不仅有无…

【vue+el-upload+vue-cropper】vue图片上传,vue-cropper图片裁剪后上传

一. 先看效果演示 二. 图片上传 用的el-upload加el-image组件 html部分 <el-dialog> ...//无关代码已省略<div v-for"item in imgArr" :key"item.index"><span>{{ item.name }}</span><el-upload action"#" list-t…

【408】计算机学科专业基础 - 数据结构

数据结构知识 绪论 数据结构在学什么 如何用程序代码把现实世界的问题信息化 如何用计算机高效地处理这些信息从而创造价值 数据结构的基本概念 什么是数据&#xff1a; 数据是信息的载体&#xff0c;是描述客观事物属性的数、字符及所有能输入到计算机中并被计算机程序…

K8S知识点(十)

&#xff08;1&#xff09;Pod详解-启动命令 创建Pod&#xff0c;里面的两个容器都正常运行 &#xff08;2&#xff09;Pod详解-环境变量 &#xff08;3&#xff09;Pod详解-端口设置 &#xff08;4&#xff09;Pod详解-资源配额 修改&#xff1a;memory 不满足条件是不能正常…

揭秘:车企如何利用5R模式在数位行销领域取得突破

01 车企进入“大逃杀”时间 汽车行业一边是出口“捷报频传”&#xff0c;一边是内销“压力山大”。 内销的难&#xff0c;在之前中部某省的政府“骨折价”补贴掀起的“价格战”中已经可见一斑。这一颇具标志性的事件反映了汽车行业&#xff0c;尤其是燃油车行业正处在巨大的转…

曾被揭露造假的越南,再次宣称研发成功5G芯片,这是真的么?

日前在2023 年越南国际创新展 (VIIE 2023) 上&#xff0c;越南的Viettel宣布成功研发5G芯片&#xff0c;可以应用于5G基站&#xff0c;并表示该公司已成为全球第六大芯片设备供应商。 越南是近10年来制造业发展强劲的国家之一&#xff0c;甚至还在2022年成为全球经济增长最快的…

C#多线程入门概念及技巧

C#多线程入门概念及技巧 一、什么是线程1.1线程的概念1.2为什么要多线程1.3线程池1.4线程安全1.4.1同步机制1.4.2原子操作 1.5线程安全示例1.5.1示例一1.5.2示例二 1.6C#一些自带的方法实现并行1.6.1 Parallel——For、ForEach、Invoke1.6.1 PLINQ——AsParallel、AsSequential…

TSINGSEE视频智能分析人员入侵AI检测算法如何让城市管理更加高效、智慧?

在城市管理场景中&#xff0c;经常面临着禁区垂钓、非法捕捞、行人闯红灯、小区盗窃、车辆乱停乱放等一系列管理难题&#xff0c;这给城市发展带来了不小的阻力&#xff0c;同时也极易增加管理的人力、物力和财力。传统的人员巡逻监管效率低并且存在时间差&#xff0c;很难及时…

2.4.0 Milky Way 强势登场!新功能大爆炸,让你High翻全场!

Yo开发达人们&#xff0c;我们有重磅新功能要给你们放送啦&#xff01; Check it out 数据汇总不再单调&#xff0c;新的聚合函数登场&#xff01; compact_state_agg #1359gauge_agg #1370first #1395last #1413mode #1440increase #1476delta #1395time_delta #1405rate #14…

内存映射:PS和PL DDR3的一些区别

之前写的一些资料&#xff1a; PS与PL互联与SCU以及PG082-CSDN博客 参考别人的资料&#xff1a; PL读写PS端DDR的设计_pl读写ps端ddr数据-CSDN博客 xilinx sdk、vitis查看地址_vitis如何查看microblazed地址_yang_wei_bk的博客-CSDN博客 可见&#xff0c;PS端的DDR3需要从…

从0到1实现一个前端监控系统(附源码)

目录 一、从0开始 二、上报数据方法 三、上报时机 四、性能数据收集上报 收集上报FP 收集上报FCP 收集上报LCP 收集上报DOMContentLoaded 收集上报onload数据 收集上报资源加载时间 收集上报接口请求时间 五、错误数据收集上报 收集上报资源加载错误 收集上报js错…

msvcp120.dll丢失的6种解决方法,教你如何修复dll文件丢失

“找不到msvcp120dll,无法继续执行代码的6个修复方案”。我相信很多朋友在运行某些程序时&#xff0c;可能会遇到这样的错误提示&#xff1a;“找不到msvcp120dll&#xff0c;无法继续执行代码”。那么&#xff0c;msvcp120dll究竟是什么&#xff1f;为什么会丢失呢&#xff1f…

Java基础知识第四讲:Java 基础 - 深入理解泛型机制

Java 基础 - 深入理解泛型机制 背景&#xff1a;Java泛型这个特性是从JDK 1.5才开始加入的&#xff0c;为了兼容之前的版本&#xff0c;Java泛型的实现采取了“伪泛型”的策略&#xff0c;即Java在语法上支持泛型&#xff0c;但是在编译阶段会进行所谓的“类型擦除”&#xff0…

NestJS——基于Node.js 服务器端应用程序的开发框架

文章目录 前言什么是 NestJS&#xff1f; 一、NestJS特性&#xff1f;二、使用步骤Typescript 知识后端开发基本知识新建项目目录结构 前言 Nestjs中文文档 什么是 NestJS&#xff1f; Nest (NestJS) 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的开发框架。它利用…

【JVM系列】- 寻觅·方法区的内容

寻觅方法区的内容 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f31d;分享学习心得&#xff0c;欢迎指正&#xff0c;大家一起学习成长&#xff01; 文章目录 寻觅…

杂记 | 使用FRP搭建内网穿透服务(新版toml配置文件,搭配反向代理食用)

文章目录 01 需求与回顾02 下载程序包03 编辑.toml文件3.1 编辑frps.toml3.2 编辑frpc.toml 04 启动服务4.1 启动服务端4.2 启动客户端 05 配置反向代理&#xff08;可选&#xff09;06 windows设置为默认启动&#xff08;可选&#xff09;6.1 创建启动脚本6.2 设置为开机自启 …

【Spring Cloud】声明性REST客户端:Feign

Spring Cloud Feign ——fallback 服务降级 1. Feign 简介2. Feign 的基础使用2.1 普通 HTTP 请求2.2 Feign 远程调用上传文件接口 1. Feign 简介 Feign 是一个声明式的 HTTP 客户端&#xff0c;它简化了编写基于 REST 的服务间通信代码的过程。在 Spring Cloud 中&#xff0c…

你一定要学会的Java语法 -- 【继承】

书接上回&#xff0c;我们已经学完了类和对象&#xff0c;今天内容可能有一点难&#xff0c;相信自己能跨过这道坎。 目录 一. 继承 1.什么是继承 2. 继承的概念 3. 继承的语法 4.父类成员访问 子类和父类成员变量同名 子类和父类成员方法同名 5.super关键字 6.子类构…

POJ 3254 Corn Fields 状态压缩DP(铺砖问题)

一、题目大意 我们要在N * M的田地里种植玉米&#xff0c;有如下限制条件&#xff1a; 1、对已经种植了玉米的位置&#xff0c;它的四个相邻位置都无法继续种植玉米。 2、题目中有说一些块无论如何&#xff0c;都无法种植玉米。 求所有种植玉米的方案数&#xff08;不种植也…

Vector - CANoe - Vector Hardware Manager基础介绍

经常使用CANoe的人都知道&#xff0c;我们之前使用配置VN系列硬件通道的时候使用的是Vector Hardware Config&#xff0c;非常的方便&#xff0c;不过在Vector Driver Setup驱动版本大于22.14后&#xff0c;为了更好的适用车载以太网相关的配置&#xff0c;以及各个配置之间继承…