【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.mzph.cn/news/603622.shtml

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

相关文章

第15课 利用openCV实现人脸识别

这节课&#xff0c;我们再来看一个简单且实用的例子&#xff1a;人脸识别。这个小例子可以让你进一步领略openCV的强悍。 1.复制demo14并改名为demo15。 2.修改capImg函数&#xff1a; int fmle::capImg() {// 加载人脸检测分类器cv::CascadeClassifier faceCascade;faceCas…

UEditor在编辑对齐方式时产生额外空行问题

一、问题描述 一个关于UEditor富文本编辑器的问题&#xff1a;在编辑内容对齐方式后保存后浏览器显示的段落上下会比原先多出一些间距。 下面是对齐编辑后&#xff0c;未保存前的的HTML&#xff1a; 保存后&#xff0c;实际会多出一个段落空行&#xff1a; 二、问题调查 经…

基于B/S架构的数字孪生智慧监所可视化监管系统

1 前言 物联网技术的发展使云计算技术得到了迅猛的发展及广泛的应用&#xff0c;智能体系的创建已经成为监狱发展的必然趋势。 智慧监狱的创建、智能化管理的推行是监狱管理的创新&#xff0c;也是监狱整体工作水平提升的具体体现。 1.1 建设背景 近年来&#xff0c;司法部不…

CISSP 第7章:PKI和密码学应用

第七章 PKI和密码学应用 7.1 非对称密码学 对称密码系统具有共享的秘钥系统&#xff0c;从而产生了安全秘钥分发的问题 非对称密码学使用公钥和私钥对&#xff0c;无需支出复杂密码分发系统 7.1.1 公钥与私钥 7.1.2 RSA&#xff08;兼具加密和数字签名&#xff09; RSA算法依赖…

ctrl + v获取图片和文字

1、效果实现 1.1、做法 容器监听paste事件。原生js则document.addEventListener(paste)&#xff0c;vue则paste 监听paste事件的回调函数有个参数e&#xff0c;获取e.clipboardData粘贴的文字信息 e.clipboardData.getData("text/plain")粘贴的图片信息 e.clipboard…

委托QAbstractItemDelegate

参考&#xff1a;QT(7)-初识委托_qt 委托-CSDN博客 一、 1、 模型&#xff1a;负责“组织”数据&#xff1b; 视图&#xff1a;负责“显示”数据&#xff1b; 委托&#xff1a;负责“修改”数据&#xff1b; 2、委托&#xff1a;在QT的MV模型中&#xff0c;处理特定类型的…

c++拷贝控制

文章目录 拷贝构造函数的基本概念定义语法何时使用拷贝构造函数示例代码运行结果注意事项 拷贝赋值运算符的基本概念定义语法何时使用拷贝赋值运算符示例代码运行结果注意事项 析构函数的基本概念定义语法何时调用析构函数示例代码运行结果注意事项 三/五法则三法则 (Rule of T…

【SpringCloud】之配置中心(进阶使用)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《SpringCloud开发之远程消费》。&#x1f3af;&a…

精彩推荐 |【Java技术专题】「重塑技术功底」攻破Java技术盲点之剖析动态代理的实现原理和开发指南(上)

攻破Java技术盲点之剖析动态代理的实现原理和开发指南 背景介绍静态代理和动态代理动态代理与静态代理的区别 进入正题重温&#xff1a;静态代理实现静态代理案例静态代理的弊端 重温&#xff1a;动态代理Java动态代理InvocationHandlerJava动态代理的实现下面看具体的代码实例…

Blazor项目如何调用js文件

以下是来自千问的回答并加以整理&#xff1a;&#xff08;说一句&#xff0c;文心3.5所给的回答不完善&#xff0c;根本运行不起来&#xff0c;4.0等有钱了试试&#xff09; 在Blazor项目中引用JavaScript文件&#xff08;.js&#xff09;以实现与JavaScript的互操作&#xff…

基于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.…

Java 11中的新字符串APIs详解

第1章 引言 大家好&#xff0c;我是小黑&#xff0c;咱们都知道&#xff0c;Java作为一种广泛使用的编程语言&#xff0c;每一次更新都会带来不少新鲜事物。而Java 11&#xff0c;作为长期支持&#xff08;LTS&#xff09;版本之一&#xff0c;更是引起了广大开发者的关注。好…

并发(8)

目录 46.Thread.sleep(),Object.wait(),Condition.await(),LockSupport.part()的区别&#xff1f; 47.如果在wait&#xff08;&#xff09;之前执行了notify&#xff08;&#xff09;会怎样&#xff1f; 48.如果在park()之前执行了unpark()会怎样&#xff1f; 49.什么是AQS&…

九州金榜|孩子厌学,作为父母有想做自己的原因吗?

孩子不会天生就厌学&#xff0c;如果孩子天生厌学&#xff0c;那么孩子就不可能学会说话&#xff0c;走路&#xff0c;日常生活&#xff0c;更不可能去上学&#xff0c;孩子厌学因素非常多&#xff0c;而作为父母&#xff0c;你有没有想过是你的原因造成的呢&#xff1f;九州金…

编程语言的未来,通用代码生成器和超级语言

编程语言的未来&#xff0c;通用代码生成器和超级语言 我们生活在一个编程语言种类繁多&#xff0c;百花齐放的年代。形形色色的编程语言覆盖了软件开发的方方面面。如果说这些变成语言有什么共性的话&#xff0c;大家都知道&#xff0c;大多数编程语言是高级语言。 何为高级…

K8S---通过curl访问api

1、列出所有的接口 curl --cacert /opt/kubernetes/ssl/ca.pem --cert /opt/kubernetes/ssl/default-admin.pem --key /opt/kubernetes/ssl/default-admin-key.pem https://10.240.184.74:6443/ 2、列出核心api的版本 curl --cacert /opt/kubernetes/ssl/ca.pem -…

手敲MyBatis(十四章)-解析含标签的动态SQL语句

1.前言 这一章主要的就是要解析动态标签里的Sql语句&#xff0c;然后进行条件语句的拼接&#xff0c;动态标签实现了trim和if标签&#xff0c;所以Sql节点就要加上TrimSqlNode和ifSqlNode&#xff0c;我们最终要获取Sql源&#xff0c;动态Sql语句需要一些处理&#xff0c;所以…

SpringCloud系列篇:核心组件之声明式HTTP客户端组件【远程消费】

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于SpringCloud的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一. 远程消费组件是什么 二. 远程消…

竞赛练一练 第22期:NOC大赛每日一练,python题目刷题第7天,包含答案解析

题目来自:NOC大赛创客智慧编程赛项Python 复赛模拟题(一) 第一题: 编写一个彩票游戏:随机生成一个不重复的五位数作为彩票号,游戏提示用户输入一个五位整数,然后根据下面的规则判断用户是否能赢得奖金,最后要求输出彩票号和奖金。 (1)若用户输入的数字和彩票的数字完…

c语言考试代码

文章目录 文件操作题 “%”&#xff1a;格式化字符串的起始标志。 “0”&#xff1a;表示使用零来填充输出字段的宽度。 “4”&#xff1a;表示输出字段的宽度为4个字符&#xff0c;如果输出的十六进制数不足4位&#xff0c;则在左边用零进行填充。 “x”&#xff1a;表示以十六…