【C++指南】一文总结C++类和对象【上】

server/2025/2/26 11:13:41/

🌟 各位看官好,我是egoist2023

🌍 种一棵树最好是十年前,其次是现在!

🚀 今天来学习C++类和对象的语法知识

👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更多人哦

目录

类是什么

类的格式

访问限定符及类域

实例化对象

概念

对象大小

内存对齐规则

this指针

C语言的缺点

this指针的定义


类是什么

C++中 面向对象三大特性 封装、继承、多态 。今天学习类的相关知识,其是封装的体现之一。

类的格式

  • class为定义类的关键字,Stack为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。
class Stack //关键字和名字
{//成员函数void Init(){//...}private:// 成员变量int* _array;size_t _capacity;size_t _top;
}; //不能缺;
  • 为了区分成员变量,一般习惯上成员变量会加⼀个特殊标识,如成员变量前面或者后面加_ 或者m开头。
  • C++中,struct也可以定义类(兼容C中struct的用法),struct升级成了类,明显的变化是struct中可以定义函数,(class中内容默认是private保护的,struct默认是public公开的【可随意访问】)。

  • 定义在类里面的成员函数默认为inline。(这样做的好处是如果某个函数需要频繁调用,编译器可选择性展开)

访问限定符及类域

  • C++中实现封装的方式,通过访问权限选择性的将其接口提供给外部的用户使用让对象更加完善。(即只要让客户知道怎么调用即可,并不需要了解里面的底层细节)
  • public修饰的成员在类外可以直接被访问private(protecded)修饰的成员在类外不能直接被访问。访问权限直至出现下一个访问限定符为止,若没有直到类结束。
  • class默认为private,struct默认为public。
  • ⼀般成员变量都会被限制为private/protected,需要别人使用的成员函数会放为public。当然,如果有需要访问私有成员变量,可以通过调用函数接口访问私有成员变量(在类外无法直接访问,可在类内定义函数访问私有变量)
#include<iostream>
using namespace std;class Day
{
public:int GetYear() //在类里面访问私有成员变量{return _year;}
private:int _year = 1;
};int main()
{Day d;//实例化cout << d.GetYear() << endl; //调用函数接口return 0;
}
  • 类也是⼀个新的作用域,类的所有成员都在类的作用域中,在类体外定义成员时,依然使用 :: 作用域操作符指明成员属于哪个类域。
  • 类域影响的是编译的查找规则,若Init函数不指定作用域,那么编译时编译器默认从全局域寻找,找不到就会报错。指定类域就是知道Init是成员函数,当前域就会到类域中去查找。

实例化对象

概念

  • 用类类型在物理内存中创建对象的过程,称为类实例化出对象
  • 类是对象进行一种抽象描述,是一个模型一样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有分配空间,用类实例化出对象时,才会分配空间。(即只在实例化对象的时候才会开空间)
  • 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量。

看完是不是觉得很抽象,跟没看一样?打个比方 

在日常生活中,房子是司空见惯的。而房子的设计需要设计图,即 设计图 --> 房子

同理,在实例化对象当中,类就相当于是设计图(已经有人写好了,可供使用),而实例化对象就相当于房子。 即 类 --> 实例化对象

对象大小

既然类能实例化对象,开了空间意味着需要知道对象有多大,对象中肯定包含成员变量,同时要明白内存是如何对齐的。

内存对齐规则

•  第一个成员在与结构体偏移量为0的地址处。
对齐数 = 编译器默认的对齐数 与 该成员大小的较小值。(VS中默认的对齐数为8)
若要修改编译器默认对齐数,则添上如下代码
#pragma pack(4)//设置默认对齐数为4
#pragma pack()//取消设置的对齐数
其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
结构体总大小为:最大对齐数的整数倍。
如果嵌套了结构体的情况,嵌套的结构体对⻬到自己的最⼤对⻬数的整数倍处,结构体的整体大小就是所有最大对⻬数(含嵌套结构体的对⻬数)的整数倍。
此结构体对象大小为多少呢?
struct A
{int a;int b;char c;
};

根据内存对齐规则:第一个成员a在与结构体偏移量为0的地址处,占4个字节。成员b先对齐到对齐数的整数倍处,占4个字节;成员c同理。总占9个自己,由于需要对齐到最大对齐数的整数倍,因此结构体总大小为12。

那结构体内没有成员呢?

struct A
{};
运行后发现 A类对象的大小是1 ,为什么没有成员变量还要给1个字节呢?因为如果一个字节都不给,表示不了对象存在过,作用是为了占位标识对象存在。

疑惑 --> 为什么会存在内存对齐呢?

内存对齐是为了提高访问效率。

那么成员函数是否包含呢?不包含

了解:首先函数被编译后是一段指令,对象中没办法存储,这些指令存储在一个单独的区域(代码段),那么对象中非要存储的话,只能是成员函数的指针。再分析一下,对象中是否有存储指针的必要呢,Date实例化d1和d2两个对象,d1和d2都有各自独立的成员变量存储各自的数据,但是d1和d2的成员函数Init指针却是一样的,存储在对象中就浪费了。如果用Date实例化100个对象,那么成员函数指针就重复存储100次,太浪费了。

这里需要再额外哆嗦⼀下,其实函数指针是不需要存储的,函数指针是⼀个地址,调用函数被编译成汇编指令[call 地址], 其实编译器在编译链接时,就要找到函数的地址,不是在运行时找,只有动态多态是在运行时找,就需要存储函数地址。

this指针

C语言的缺点

在C语言版本中,在实现对应函数功能时,我们需要把对象的参数传过去,以便知道是哪个对象在调用对应函数。从下面程序中,每次都需要将对象的地址传过去,是非常繁琐和不方便的。因此在C++中引入了一个新的语法 --> this 指针。

#include<iostream>
using namespace std;class Date
{
public://成员变量int _year;int _month;int _day;
};void Init(Date* const d, int year, int month, int day)
{d->_year = year;d->_month = month;d->_day = day;
}void Print(Date* const d)
{cout << d->_year << "-" << d->_month << "-" << d->_day << endl;
}int main()
{Date d1;Date d2;Init(&d1,2025, 2, 28);Init(&d2,2024, 1, 14);Print(&d1);Print(&d2);return 0;
}

this指针的定义

编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加一个当前类类型的指针,叫做this 指针。
void Init(int year,int month, int day)//隐藏this指针

其原型为

void Init(Date* const this, int year,int month, int day)

这里补充一点,this指针加const的原因是为了使代码更加健壮,其目的是不改变this指针变量本身,可以改变this指针指向的内容,

类的成员函数中访问成员变量,本质都是通过this指针访问的。
C++规定不能在实参和形参的位置显示的写this指针(编译时编译器会处理),但是可以在函数体内显示使用this指针
void Init(int year, int month, int day)
{//显示传this指针this->_year = year;this->_month = month;this->_day = day;
}

设计出这个语法大大方便了程序员,将工作交给编译器来处理,并且使代码简洁且容易理解。如下便是C++版本中this指针作用的程序。

#include<iostream>
using namespace std;class Date
{
public://成员函数void Init(int year,int month,int day)//隐藏的第一个参数为this指针{//this->_year=year;//可在函数内显示调用_year = year;_month = month;;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}private://成员变量int _year;int _month;int _day;
};int main()
{Date d1;Date d2;d1.Init(2025, 2, 28);d2.Init(2024, 1, 14);d1.Print();d2.Print();return 0;
}


http://www.ppmy.cn/server/170728.html

相关文章

【星云 Orbit-F4 开发板】03a. 按键玩法一:独立按键定时中断扫描法

【星云 Orbit-F4 开发板】03b. 按键玩法一&#xff1a;独立按键中断扫描法 概述 本教程基于STM32F407 HAL库&#xff0c;实现模块化的定时中断按键扫描功能&#xff0c;采用去抖动算法与自锁机制确保稳定检测。代码分为按键模块、蜂鸣器模块、定时器模块及主程序&#xff0c;…

【漫话机器学习系列】105.学习速率(Learning Rate)

学习速率&#xff08;Learning Rate&#xff09;及其影响 学习速率&#xff08;Learning Rate, LR&#xff09;是机器学习和深度学习中的关键超参数&#xff0c;它决定了模型在训练过程中参数更新的步长。学习速率的选择直接影响训练的效率和最终模型的性能。本文将结合图示深…

WPS中Word表格做好了,忘记写标题了怎么办?

大家好&#xff0c;我是小鱼。 在使用wps制作Word表格时经常会遇到这种情况&#xff0c;就是辛辛苦苦把word表格制作好了&#xff0c;却突然发现忘了为表格添加标题了。怎么都没法为表格重写添加标题&#xff0c;真是一阵操作猛如虎&#xff0c;结果觉得表格真是白做了。其实&…

Linux编译工具链

文章目录 编译工具链1. 编译1.1 GCC其他选项1.2 条件编译1.2.1 条件编译的作用 2. 调试2.1 进入GDB调试界面2.2 调试程序查看源代码设置断点查看断点删除断点启动调试继续忽略断点n次单步调试跳出函数逐过程监视查看内存退出GDB 2.3 调试coredump文件查看系统是否允许生成Cored…

从卡顿到丝滑:火山引擎DeepSeek-R1引领AI工具新体验

方舟大模型体验中心全新上线&#xff0c;免登录体验满血联网版Deep Seek R1 模型及豆包最新版模型:https://www.volcengine.com/experience/ark?utm_term202502dsinvite&acDSASUQY5&rcGO9H7M38 告别DeepSeek卡顿&#xff0c;探索火山引擎DeepSeek-R1的丝滑之旅 在A…

QSplashScreen --软件启动前的交互

目录 QSplashScreen 类介绍 使用方式 项目中使用 THPrinterSplashScreen头文件 THPrinterSplashScreen实现代码 使用代码 使用效果 QSplashScreen 类介绍 QSplashScreen 是 Qt 中的一个类&#xff0c;用于显示启动画面。它通常在应用程序启动时显示&#xff0c;以向用户显…

Golang学习笔记_38——享元模式

Golang学习笔记_35——代理模式 Golang学习笔记_36——装饰器模式 Golang学习笔记_37——外观模式 文章目录 享元模式&#xff08;Flyweight Pattern&#xff09;详解一、核心概念1. 定义2. 解决的问题3. 核心角色4. 类图 二、特点分析三、适用场景1. 文字编辑器2. 游戏开发3. …

嵌入式项目:STM32刷卡指纹智能门禁系统

本文详细介绍基于STM32的刷卡指纹智能门禁系统。 获取资料/指导答疑/技术交流/选题/帮助&#xff0c;请点链接&#xff1a; https://gitee.com/zengzhaorong/share_contact/blob/master/stm32.txt 1 系统功能 1.1 功能概述 本系统由STM32硬件端&#xff08;下位机&#xff09;…