【C++】- 类和对象(!!C++类基本概念!this指针详解)

类和对象

  • 引入类
  • 类的定义
  • 类的访问限定操作符
  • 类的作用域
  • 类的实例化
  • 类对象模型
  • this指针

引入类

在 C++中,引入了一个新的定义----------是一种用户自定义的数据类型,用于封装数据和行为。类可以看作是一个模板或蓝图,描述了一组相关的数据和对这些数据的操作方式。通过类,可以创建具体的对象来使用和操作这些数据。

类是C++面向对象编程的核心,为了便于理解,我们可以将类抽象成一架飞机:
在这里插入图片描述

学习了C语言之后,我们知道了结构体类型,但在C语言结构体内只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。在这里插入图片描述

我们在C++中,用struct实现链表,可以将我们的一系列函数放进去,而这些在C++中更喜欢用class来代替。

在这里插入图片描述

在 C++ 中,structclass 都可以用于定义自定义数据类型,它们的区别主要有以下两点:

  1. 默认访问权限不同:struct 的默认访问权限是公有的,而 class 的默认访问权限是私有的。这意味着在 struct 中定义的成员变量和成员函数是公有的,可以被外部访问;而在 class 中定义的成员变量和成员函数是私有的,只能在类内部访问。

  2. 继承方式不同:在没有显式指定继承方式时,class 的继承方式是私有继承(private),而 struct 的继承方式是公有继承(public)。即如果一个类没有指定继承方式,则其默认继承方式与其类型相同。

类的定义

类的基本定义形式是:

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

类体内的内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为成员函数

在这里插入图片描述
在这里插入图片描述这里注意!在类内直接定义的函数 会被默认视为内联函数,但并不意味着所有在类内定义的函数都是内联函数。

内联函数是一种编译器优化的机制,它将函数的定义体直接插入到调用该函数的地方,而不是通过函数调用的方式执行。这样可以减少函数调用的开销,提高程序的执行效率。
就像这样直接插入:
在这里插入图片描述

在这里插入图片描述在类内定义的函数,默认情况下会被视为内联函数。但是,如果函数体过于庞大复杂,编译器可能会忽略内联函数的请求,将其视为普通函数进行处理。因此,并不是所有在类内定义的函数都会被真正地内联。。。

在这里插入图片描述通过使用 inline 关键字,可以告诉编译器将该函数作为内联函数处理。

☃ 需要注意的是,内联函数适用于简单短小的函数,且在多处调用的情况下才能发挥优势。对于复杂的函数或只在少数地方调用的函数,使用内联可能导致代码膨胀,反而降低性能。因此,在确定是否使用内联函数时,需要综合考虑函数的规模、调用频率以及性能需求等因素。

?当我们单纯的定义一个类,定义任何成员变量时,系统会为这个类开空间吗

在 C++ 中,一个类的对象大小至少为 1 字节,即使这个类没有任何成员变量。这是因为每个对象都必须在内存中占据至少一个字节的空间。
这个字节通常用于对象的地址,也就是对象所在内存地址的第一个字节。即使这个字节不存储有效数据,但是它也是必需的,因为它用于确定对象在内存中的位置和边界。

类的访问限定操作符

在C++中,类的访问限定符用于控制类的成员变量和成员函数的访问权限。C++中为我们提供了三种访问限定符:public、private和protected。

1. public:

  • 成员变量和成员函数声明为public的可以在类的外部和内部被访问。
  • public成员可以通过对象直接访问或通过类的对象调用。
  • public成员在类的继承层次中也可以被派生类访问。

2. private:

  • 成员变量和成员函数声明为private的只能在类的内部被访问。
  • private成员不能通过对象直接访问,只能通过类的成员函数来访问。
  • private成员对于类的外部是不可见的。

3. protected:

  • 成员变量和成员函数声明为protected的可以在类的内部被访问。
  • protected成员在类的继承层次中可以被派生类访问,但对于类的外部是不可见的。
  • protected成员不能通过对象直接访问,只能通过类的成员函数来访问。

默认情况下,C++中的类成员的访问限定符是private。这意味着如果没有显式地指定访问限定符,那么成员变量和成员函数都将被视为private成员。

代码演示:

#include <iostream>
using namespace std;class MyClass {
public:int publicVar;void publicFunc() {cout << "publicFunc is called" << endl;}protected:int protectedVar;void protectedFunc() {cout << "protectedFunc is called" << endl;}private:int privateVar;void privateFunc() {cout << "privateFunc is called" << endl;}
};int main() {MyClass obj;obj.publicVar = 1;obj.publicFunc();return 0;
}

在上面的代码中,我们定义了一个名为MyClass的类,并且使用了三种不同的访问限定符来限制成员的访问权限。在main函数中,我们创建了一个MyClass类的对象obj,并且访问了publicVar和publicFunc方法,因为它们都是公共成员。但是我们不能访问protectedVar、protectedFunc、privateVar和privateFunc方法,因为它们只能在类内部访问。如果尝试访问它们,编译器会报错。

通过使用不同的访问限定符,我们可以控制类的成员在何处可见和可访问。这有助于实现信息隐藏和封装的概念,使得类的实现细节对于外部用户来说是不可见的,从而提高代码的安全性和可维护性。

类的作用域

在C++中,类的作用域是指类中成员的可见范围。类的作用域可以分为两个部分:类的内部作用域和类的外部作用域。

  • 类的内部作用域:在类的内部,成员函数和成员变量可以直接访问类中的其他成员,无需使用作用域解析运算符::来限定。在成员函数中,可以直接访问该类的所有成员,包括私有、保护和公共成员。
  • 类的外部作用域:在类的外部,需要使用作用域解析运算符::来限定访问类中的成员。通过类名加上作用域解析运算符,可以访问该类的公共成员和静态成员。私有和保护成员无法在类外部直接访问。

在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。作用域操作符在博主在这里插入图片描述C++入门篇 有讲解

类的实例化

类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图。
在这里插入图片描述

类对象模型

类在内存中的存储模式如下:
在这里插入图片描述

在计算类对象的大小时,一般只需要考虑成员变量的大小,而不需要计算成员函数的大小。成员函数在对象中并不占据实际的内存空间,它们只是一组指向类的成员函数代码的指针。这些指针共享存储在类的静态区域中,并且对于每个类的所有对象来说是相同的。因此,成员函数不会影响类对象的大小。

总结起来,计算类对象的大小只需要考虑成员变量的大小,而成员函数和虚函数表对于类对象的大小没有直接影响。

this指针

在C++中,每个对象都有一个指向自己的指针,这个指针就是this指针。this指针是一个隐含于每个非静态成员函数中的特殊指针,它指向调用该函数的对象。在C++中,成员函数可以直接访问对象的数据成员,因为在成员函数内部,this指针指向当前对象的地址,通过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(2022,1,11);d2.Init(2022, 1, 12);d1.Print();d2.Print();return 0;
}

???Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调用 Init 函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?

在这里插入图片描述在C++中,对象在调用成员函数时,编译器会自动将该对象的地址作为this指针传递给成员函数。在Init函数中,通过this指针访问对象的成员变量,确保将值设置到正确的对象中。

因此,当d1调用Init函数时,Init函数内部的操作会通过this指针访问d1对象的成员变量,即将值设置到d1对象的_year、_month和_day成员变量中;同样,当d2调用Init函数时,Init函数内部的操作会通过this指针访问d2对象的成员变量,将值设置到d2对象的成员变量中。这样就实现了不同对象之间的区分。当然最后,当d1和d2调用Print函数时,会打印出各自的年月日信息。

只不过这些所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。在这里插入图片描述

在这里插入图片描述

this指针在C++中具有以下特性:

  1. this指针的类型是类类型的指针,即类类型* const。这意味着this指针是一个常量指针,指向当前对象的地址,不可以被修改。

  2. this指针只能在成员函数内部使用。它代表当前对象的地址,并且只有在成员函数内部才能访问到该指针。

  3. this指针本质上是成员函数的一个隐式形参。当对象调用成员函数时,编译器会将对象的地址作为实参传递给this指针,使得成员函数可以通过this指针来访问对象的成员变量和成员函数。

  4. this指针是成员函数的第一个隐含参数,一般情况下由编译器自动传递,不需要用户显式传递。

  5. 对象本身并不存储this指针,它只是在成员函数调用时被传递给this指针。

通过使用this指针,我们可以在成员函数内部访问对象的成员变量和函数,确保每个对象在调用成员函数时可以正确地操作自己的数据。this指针的存在使得对象的成员函数可以区分不同的对象,并在函数内部对各个对象进行操作。

在这里插入图片描述this指针是C++中一个非常重要的概念,也是面向对象编程中不可或缺的一部分。它可以让成员函数访问对象的成员变量和成员函数,避免命名冲突,返回对象本身的引用等。在使用this指针时,需要注意当前对象是否存在,以及函数内部是否正确处理对象的生命周期和有效性。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 集成vendor下的模块

Android 集成vendor下的模块 &#xff0c;只需要在 PRODUCT_PACKAGES 加上对应的模块名&#xff0c;编译的时候就会执行对应模块的bp文件&#xff0c;集成到系统中 PRODUCT_PACKAGES \WallpaperPicker \Launcher3 \com.nxp.nfc Android11 Framework Vendor下自定义系统…

SpringBoot 如何 返回页面

背景 RestController ResponseBody Controller Controller中的方法无法返回jsp页面&#xff0c;或者html&#xff0c;配置的视图解析器 InternalResourceViewResolver不起作用&#xff0c;返回的内容就是Return 里的内容。 Mapping ResponseBody 也会出现同样的问题。 解…

nginx访问路径匹配方法

目录 一&#xff1a;匹配方法 二&#xff1a;location使用: 三&#xff1a;rewrite使用 一&#xff1a;匹配方法 location和rewrite是两个用于处理请求的重要模块&#xff0c;它们都可以根据请求的路径进行匹配和处理。 二&#xff1a;location使用: 1&#xff1a;简单匹配…

SSH 密钥身份验证和管理

安全外壳协议&#xff08;Security Shell Protocol&#xff09;是一种应用于计算机网络的安全通信协议&#xff0c;其提供的服务可用于保护网络上的连接和数据传输安全性&#xff0c;其核心思想是为网络上的两台计算机之间搭建一个安全的外壳&#xff0c;以保护数据传输的安全性…

Python中的装饰器

顾名思义&#xff0c;函数装饰器就是对这个函数进行了装饰&#xff0c;比如在函数的前后进行日志打印等。在Python中&#xff0c;装饰器是一种特殊的语法&#xff0c;用于简化函数或方法的定义和调用。装饰器允许你在不修改原始函数代码的情况下&#xff0c;通过在其上应用装饰…

Ubuntu本地快速搭建web小游戏网站,公网用户远程访问

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;…

css文本溢出处理——单行、多行

日常开发中&#xff0c;经常会遇到需要展示的文本过长&#xff0c;这种情况下&#xff0c;为了提高用户的使用体验&#xff0c;最常见的处理方式就是把溢出的文本显示成省略号。 处理文本的溢出的方式&#xff1a;1&#xff09;单行文本溢出&#xff1b; 2&#xff09;多行文本…

TIA Portal 各版本安装指南

TIA Portal下载链接 https://pan.baidu.com/s/1Jat53vGz1rXfLm7kTldz-Q?pwd0531 1.鼠标右击【TIA portal V19 (64bit)】压缩包&#xff08;先点击“显示更多选项”&#xff09;选择【解压到 TIA portal V19 (64bit)】。 2.打开解压后的文件夹&#xff0c;鼠标右击【NoRestart…

Hive实战:分科汇总求月考平均分

文章目录 一、实战概述二、提出任务三、完成任务&#xff08;一&#xff09;准备数据1、在虚拟机上创建文本文件2、上传文件到HDFS指定目录 &#xff08;二&#xff09;实现步骤1、启动Hive Metastore服务2、启动Hive客户端3、创建分区的学生成绩表4、按分区加载数据5、查看分区…

系统学英语 — 音标音节 — 能读就能写

目录 文章目录 目录概览12 个单元音8 个双元音28 个辅音音节 概览 音标发音器&#xff1a;https://en-yinbiao.xiao84.com/biao/ 12 个单元音 序号发音音标助记字母组合备注1拖长音 前元音[i:]eate、ea、ee、ie2短促音 前元音[i]bige、i、y3拖长音 后元音[a:]aska、ar4短促…

完善 Golang Gin 框架的静态中间件:Gin-Static

Gin 是 Golang 生态中目前最受用户欢迎和关注的 Web 框架&#xff0c;但是生态中的 Static 中间件使用起来却一直很不顺手。 所以&#xff0c;我顺手改了它&#xff0c;然后把这个改良版开源了。 写在前面 Gin-static 的改良版&#xff0c;我开源在了 soulteary/gin-static&a…

【开源】基于JAVA语言的服装店库存管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 角色管理模块2.3 服装档案模块2.4 服装入库模块2.5 服装出库模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 角色表3.2.2 服装档案表3.2.3 服装入库表3.2.4 服装出库表 四、系统展示五、核心代码5.…

STM32之模拟IIC总线控制SHT20温湿度芯片

一、IIC总线概述 1、IIC总线介绍 I2C (Inter&#xff0d;Integrated Circuit)总线产生于在80年代&#xff0c; 由PHILIPS公司开发的两线式串行总线&#xff0c;用于连接微控制器及其外围设备, 最初为音频和视频设备开发。I2C总线两线制包括&#xff1a;串行数据SDA&#xff08…

Rustdesk打开Win10 下客户端下面服务不会自启,显示服务未运行

环境: Rustdesk1.19 问题描述: Rustdesk打开Win10 下客户端下面服务不会自启,显示服务未运行 解决方案: 1.查看源代码 pub async fn start_all() {crate::hbbs_http::sync::start();let mut nat_tested = false;check_zombie()

银行十大主题域

当事人、产品、协议、事件、资产、财务、机构、地域、营销、渠道 便于记忆&#xff1a; 银行是一个企业&#xff0c;同时也是一个机构&#xff0c;涉及企业机构就会有资产&#xff0c;财务的存在&#xff0c;银行有自己的产品&#xff08;信用卡&#xff0c;黄金&#xff0c;期…

【小沐学CAD】开源Assimp库导入三维模型(C++、Python)

文章目录 1、简介2、下载编译3、代码测试3.1 C3.2 pyassimp&#xff08;Python&#xff09; 结语 1、简介 https://github.com/assimp/assimp Open Asset Import Library 是一个库&#xff0c;用于将各种 3D 文件格式加载为共享的内存格式。它支持 40 多种用于导入的文件格式和…

PDF.js实现搜索多个不同的关键词高亮显示效果

static\PDF\web\viewer.js 392行左右 // 自定义搜索关键词---------------------------------------- this.searchKeywords = keyword => {if (typeof PDFViewerApplication !== undefined) {PDFViewerApplication.eventBus.dispatch(find, {query: keyword,caseSensitive:…

AQS 抽象队列同步器

AQS AQS &#xff08;抽象队列同步器&#xff09;&#xff1a; AbstractQueuedSynchronizer 是什么 来自jdk1.5&#xff0c;是用来实现锁或者其他同步器组件的公共基础部分的抽象实现&#xff0c;是重量级基础框架以及JUC的基石&#xff0c;主要用于解决锁分配给谁的问题整体…

互联网演进历程:从“全球等待”到“全球智慧”的技术革新与商业变革

文章目录 一、导言二、World Wide Wait (全球等待)阶段1. 技术角度2. 用户体验3. 企业收益4. 教育影响 三、World Wide Web (万维网)阶段1. 技术角度2. 用户体验3. 企业收益4. 教育影响 四、World Wide Wisdom (全球智慧)阶段1. 技术角度2. 用户体验3. 企业收益4. 教育影响 五、…

MySQL——用户管理

目录 一.用户管理 二.用户 1.用户信息 2.创建用户 3.删除用户 4. 修改用户密码 三.数据库的权限 1.给用户授权 2.回收权限 一.用户管理 如果我们只能使用root用户&#xff0c;root的权限非常大,这样存在安全隐患。这时&#xff0c;就需要使用MySQL的用户管理&#xff…