当前位置: 首页 > news >正文

C++类和对象(上)

在这里插入图片描述

文章目录

  • 🦍1. 面向过程和面向对象
  • 🦧2. 类的引入
  • 🐶3. 类的定义
  • 🦮4. 类的访问控制和封装
    • 🍖4.1 访问限定符
    • 🍖4.2 封装
  • 🐩5. 类的作用域
  • 🐅6. 类的实例化
  • 🐄7. 类的大小计算
  • 🦌8. this指针
    • 🥕8.1 引子
    • 🥕8.2 this指针特性

🦍1. 面向过程和面向对象

C语言是一门面向过程的编程语言,面向过程更注重于解决问题的步骤和流程。而C++是基于面向对象的,关注的是对象之间的交互,。我们将数据和相关的功能封装在一起,形成对象。每个对象都有自己的属性(数据)和方法(功能)。

以做一道青椒肉丝来说

我们需要厨师、青椒、肉丝、锅、铲、油、盐、老抽等物品,然后再准备烹饪。先放油,油热再放肉丝,肉丝炒的差不多之后再放青椒,然后再放入盐、老抽,最后装盘,这些就属于面向过程;

在面向对象编程中,我们会将青椒肉丝看作一个对象,并定义该对象的属性和方法。

对象:青椒肉丝

  • 属性:青椒、肉片、调味料等
  • 方法:准备食材、炒菜、调味、出锅等

我们可以创建一个青椒肉丝对象,并调用对象的方法来完成烹饪过程。每个方法内部可以封装相应的逻辑和操作。

例如,调用青椒肉丝对象的"准备食材"方法,内部会包含切青椒、切肉片和腌制肉片的操作。调用"炒菜"方法时,内部会进行炒肉片和炒青椒的步骤。通过调用对象的方法,我们可以按照特定的顺序和逻辑来完成整个烹饪过程。

面向过程适用于简单的、直线式的问题,或者强调步骤和算法的场景。面向对象适用于复杂的、需要模拟真实世界的问题,或者强调对象之间关系和交互的场景。现在市面上主流的编程语言基本上都是面向对象:C++、Java、Python等。

🦧2. 类的引入

在C语言中,结构体就可以封装多个对象用来描述一些负责的事物。在C++中,将结构体升级成了,不仅可以定义变量,还可以定义函数。

struct Stack
{//方法(函数)void Init(int defaultCapacity = 4){a = (int*)malloc(sizeof(int) * 4);if (nullptr == a){perror("malloc fail");exit(-1);}capacity = defaultCapacity;top = 0;}void Push(int x){//...;}void Destory(){free(a);a = nullptr;top = capacity;}//...//成员变量(属性)int* a;int top;int capacity;
};
int main()
{//兼容C语言struct Stack s1;//C++Stack st2;st2.Init();st2.Push(1);st2.Push(2);st2.Destory();return 0;
}

🐶3. 类的定义

虽然struct可以定义类,但是为了区分C语言,C++更喜欢用class来定义类。

class定义为类的关键字,后面紧跟类名,{}为类的主体。

class ClassName {
private:// 成员变量(私有)DataType memberVariable1;DataType memberVariable2;...public:// 构造函数ClassName();  // 默认构造函数ClassName(parameter1, parameter2, ...);  // 带参数的构造函数// 成员函数(公有)ReturnType memberFunction1(parameter1, parameter2, ...);ReturnType memberFunction2(parameter1, parameter2, ...);...
};
  1. 使用 class 关键字来定义类,后面紧跟着类名(通常遵循命名约定,使用驼峰命名法)。
  2. 在类定义中,我们可以声明成员变量和成员函数。
  3. 成员变量是类的数据成员,表示类的特征或状态。它们在私有部分(private)进行声明,只能在类的内部访问。
  4. 构造函数是一种特殊的成员函数,用于创建和初始化类的对象。在示例中,我们展示了默认构造函数和带参数的构造函数的定义。构造函数的名称与类名相同,没有返回类型。
  5. 成员函数是类的行为和操作。它们在公有部分(public)进行声明,并可以包含任意的参数和返回类型。成员函数可以访问类的成员变量,执行特定的操作。

类也可以声明和定义分离:image-20230602225600452

类里面定义的函数,默认是内联函数,但具体也还是编译器决定是否为内联函数。

🦮4. 类的访问控制和封装

🍖4.1 访问限定符

当使用class来定义时,程序编译报错,我们定义的这些方法,无法访问。

image-20230602230302312

这些是因为C++中类进行了封装和访问控制,用三种修饰符来实现:

  1. private(私有): 成员被声明为 private 时,它们只能在类的内部访问。私有成员对于类的外部是不可见的,外部代码无法直接访问它们。
  2. public(公有): 成员被声明为 public 时,它们可以在类的内部和外部被访问。公有成员对外部代码可见,可以通过类的对象访问和操作。
  3. protected(保护): 成员被声明为 protected 时,它们与私有成员类似,只能在类的内部和派生类中访问。受保护成员对于外部代码是不可见的,但可以在派生类中被继承和访问。

访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止。

class如果不设置访问限定符,默认为private

struct因为要兼容C语言,所以默认为public

🍖4.2 封装

面向对象的三大特性:封装继承多态

在面向对象的封装中,类是封装的基本单位,类封装了数据成员和成员函数。封装的主要目的是将相关的数据和操作组织在一起,形成一个独立的实体,对外部隐藏其内部实现细节,只提供公共接口。

比如说,我们国家的博物馆里面的展品,大部分都会设置阻隔,我们观众可以参观,但是无法直接接触到这些展品。这在一定程度上保护了这些展品,同时也规范了观众的行为,满足了观众的基本需求。

在程序中,封装也是如此,通过将数据和操作封装在一起,实现了数据的隐藏和保护。

🐩5. 类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域

class MyClass {
public:int publicMember;  // 公有成员void PrintInfo();
private:int privateMember;  // 私有成员protected:int protectedMember;  // 受保护成员
};//指定PrintInfor属于MyClass这个类域
void MyClass::PrintInfo()
{cout << "MyClass" << endl;
}int main() {MyClass myObject;myObject.publicMember = 10;  // 可访问公有成员myObject.PrintInfo();// 以下代码将导致编译错误,无法访问私有成员和受保护成员// myObject.privateMember = 20;// myObject.protectedMember = 30;return 0;
}

🐅6. 类的实例化

类的实例化是指根据类的定义创建一个具体的对象,使其具备类所定义的属性和行为。

我们定义一个类:

class Person
{
public:void showInfo(){cout << "xxx" << endl;//...}
private:char* _name;char* _sex;int _age;
};

这里并没有实例化,只是描述出了一个人应该具备的基本属性。

//直接声明对象变量静态实例化对象
Person P1;Person P2;

实例化对象 P1、P2。

类就好比一张食谱,食谱上面有许多道菜的做法,但没有实际的菜存在,所以定义出一个类并没有分配实际的内存空间来存储它

我们将其实例化,就是把这道菜做出来呈现在我们眼前,它实际存在占据物理空间

image-20230603010005043

🐄7. 类的大小计算

class MyClass
{
public:void Print(){cout << "MyClass" << endl;}
private:int a;
};int main()
{cout << sizeof(MyClass) << endl;return 0;
}

类中既有成员变量,又有成员函数,那么这在计算内存的时候,是如何计算的呢?

// 类中既有成员变量,又有成员函数
class A1 {
public:void f1() {}
private:int _a;
};// 类中仅有成员函数
class A2 {
public:void f2() {}
};// 类中什么都没有---空类
class A3
{};int main()
{cout << sizeof(A1) << endl;cout << sizeof(A2) << endl;cout << sizeof(A3) << endl;
}

执行该程序得出:

4

1

1

我们发现,类的大小,计算的是该类中的成员变量之和,并没有算入函数;而没有成员变量或者是空类,大小为1byte

这是因为成员函数是共享给所以该类的使用对象使用的代码,并不直接存储在该类中。

打个比方:

假设我们有一个小区,里面有很多房屋,每个房屋都有自己的卧室、客厅、厨房等空间,这些就代表着类对象中的数据成员。

但是小区里面会有公共的篮球场、公园等空间,这些并没有算在自己房子的大小之内,属于公共区域,供小区居民共享使用的。

在这个比喻中,房屋可以类比为类对象的数据成员,而篮球场可以类比为类的成员函数。房屋占用实际的空间,我们说房子多大就是自己的房子有多少个平方,而篮球场作为公共设施,只是为小区居民提供服务,不会计算在房子的大小中。

类成员计算大小时,也遵循内存对齐规则——内存对齐。

🦌8. this指针

🥕8.1 引子

我们定义一个人的类Person

class Person
{
public:void Init(const std::string& n, const std::string& sex, int age){_name = n;_sex = sex;_age = age;}void Print(){cout << _name << " " << _sex << " " << _age << endl;}
private:std::string _name;std::string _sex;int _age = 0;
};int main()
{Person p1, p2;p1.Init("zhangsan", "man", 21);p2.Init("cuihua", "woman", 20);p1.Print();p2.Print();
}

Person类中,有InitPrint两个成员函数,我们刚才说到,成员函数并没有算入类的空间中,那当p1调用InitPrint的时候,这两个函数是怎么知道是p1呢?

C++中,给每个非静态成员函数,增加了一个隐藏的指针参数,该指针指向了当前对象,函数体的所以成员变量的操作都是通过指针去访问的。这个对于我们用户来说是透明的,不需要我们来传递,编译器自动完成。

🥕8.2 this指针特性

  1. 只能在成员函数内部使用image-20230603132614252

  2. this指针是成员函数的第一个隐藏指针形参,由编译器自动传递

    由于this指针是一个形参,所以应该就和普通的参数一样存放在栈区里面,但是有些编译器会对其进行优化。

    以VS2022为例,我们发现this指针存放在了rcx中(rcx是x86架构中通用的寄存器之一)。image-20230603131734400

  3. this 指针是一个常量指针,它指向当前对象并不能被修改,也不能被显式地赋值给其他指针变量。它始终指向当前对象,无法指向其他对象。

有了这些知识储备,我们来看一下,这段程序的运行结果是什么?

class A
{
public:void PrintA(){cout << "PrintA()" << endl;}
private:int _a;
};
class B
{
public:void PrintB(){cout << _b << endl;}
private:int _b;
};
int main()
{A* pa = nullptr;B* pb = nullptr;pa->PrintA();pb->PrintB();return 0;
}

运行发现,控制台上打印出了PrintA(),随后程序运行崩溃了。

这是因为A和B在调用各自的Print()成员函数时,没有发生解引用,因为Print()的地址不在对象中,A和B作为实参传递给了this指针。但是进入Print()函数后,由于A和B都是空,所以this指针也为空,A没有对齐解引用,而B访问了它的成员_b,本质上就是this->_b,对空指针解引用,所以会崩溃。

我们需要知道类是面向对象编程的核心概念,类是对象的蓝图,定义了对象的属性和行为,而对象则是根据类的定义创建的实体。
那本期的分享就到这里啦,如果有帮助的话,希望三连支持一下,我们下期再见,如果还有下期的话。

相关文章:

C++类和对象(上)

文章目录 &#x1f98d;1. 面向过程和面向对象&#x1f9a7;2. 类的引入&#x1f436;3. 类的定义&#x1f9ae;4. 类的访问控制和封装&#x1f356;4.1 访问限定符&#x1f356;4.2 封装 &#x1f429;5. 类的作用域&#x1f405;6. 类的实例化&#x1f404;7. 类的大小计算&a…...

JavaScript 数据透视表 DHTMLX Pivot Crack

DHTMLX Pivot JavaScript 数据透视表 - 强大的数据汇总和报告 使用我们的高速 JavaScript/HTML5 Pivot 组件可视化您的复杂数据&#xff0c;从而提高您的商业智能。 它可以帮助您以方便的方式汇总大型数据集。 主要特征 纯 JavaScript 库&#xff0c;可轻松与任何服务器端集成…...

QT链接库设置

以windows 平台为例&#xff0c;在.pro 文件中&#xff1a; 1 增加 INCLUDEPATH <头文件路径> DEPENDPATH <头文件路径> 2 LIBS -L<库目录路径> -l<库得名字> 3 设置MT、MTD、MD、MDD运行时库 win32:CONFIG(debug, debug|release): { QMAKE_CFLAGS_…...

零点起飞学Android——期末考试课本复习重点

目录 第一章 认识Android第二章 Android常见界面布局第三章 Android常用基本控件第四章 Android 高级控件第五章 Android菜单和对话框 第一章 认识Android 1. Android 界面设计被称为______。 答案&#xff1a;布局 2. Android中常见的布局包括______、______ 、______ 、____…...

Redis为什么快?

目录 Redis为什么快&#xff1f;渐进式ReHash全局哈希表渐进式ReHash 缓存时间戳 Redis为什么快&#xff1f; 纯内存访问&#xff1b; 单线程避免上下文切换&#xff1b; 渐进式ReHash、缓存时间戳&#xff1b; 前面两个都比较好理解&#xff0c;下面我们主要来说下 渐进式…...

Zabbix从入门到精通以及案例实操系列

1、Zabbix入门 1.1、Zabbix概述 Zabbix是一款能够监控各种网络参数以及服务器健康性和完整性的软件。Zabbix使用灵活的通知机制&#xff0c;允许用户为几乎任何事件配置基于邮件的告警。这样可以快速反馈服务器的问题。基于已存储的数据&#xff0c;Zabbix提供了出色的报告和…...

水声声波频率如何划分?水声功率放大器可将频率放大到20MHz吗?

水声声波频率如何划分&#xff1f;水声功率放大器可将频率放大到20MHz吗&#xff1f; 现如今我们可以在地球任意地区实现通信&#xff0c;是因为电磁波的作用。但是我们都知道海洋占了全球十分之七面积&#xff0c;电磁波在水下衰减速度太快&#xff0c;无法做到远距离传输&am…...

网络攻防技术--论文阅读--《基于自动数据分割和注意力LSTM-CNN的准周期时间序列异常检测》

英文题目&#xff1a;Anomaly Detection in Quasi-Periodic Time Series based on Automatic Data Segmentation and Attentional LSTM-CNN 论文地址&#xff1a;Anomaly Detection in Quasi-Periodic Time Series Based on Automatic Data Segmentation and Attentional LST…...

C++ 学习 ::【基础篇:08】:C++ 中 struct 结构体的认识【面试考点:C 与 C++ 中结构体的区别】

本系列 C 相关文章 仅为笔者学习笔记记录&#xff0c;用自己的理解记录学习&#xff01;C 学习系列将分为三个阶段&#xff1a;基础篇、STL 篇、高阶数据结构与算法篇&#xff0c;相关重点内容如下&#xff1a; 基础篇&#xff1a;类与对象&#xff08;涉及C的三大特性等&#…...

Electron开发:打包和发布 Electron 应用

https://start.spring.io/ 在线数据分析网站 https://tj.aldwx.com/ https://www.spsspro.com/ win10如何分屏 拖到边缘 Electron 环境搭建 https://www.electronjs.org/zh/docs/latest/tutorial/%E6%89%93%E5%8C%85%E6%95%99%E7%A8%8B electron 隐藏菜单 electron 标题栏 设…...

【每日一题Day222】LC1110删点成林 | dfs后序

删点成林【LC1110】 给出二叉树的根节点 root&#xff0c;树上每个节点都有一个不同的值。 如果节点值在 to_delete 中出现&#xff0c;我们就把该节点从树上删去&#xff0c;最后得到一个森林&#xff08;一些不相交的树构成的集合&#xff09;。 返回森林中的每棵树。你可以按…...

[ChatGPT] 从 GPT-3.5 到 GPT-5 的进化之路 | ChatGPT和程序员 : 协作 or 取代

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐如果觉得文章写的不错&#xff0c;欢迎点个关注一键三连&#x1f609;有写的不好的地方也欢迎指正&#xff0c;一同进步&#x1f601;…...

6.4 GDP调试多进程程序

目录 GDB调试多进程程序 安装gdb gdb编译 运行gdb 单步运行 从头到尾运行 下一步 运行子进程 同时运行父进程 查看运行的进程 切换进程 退出 GDB调试多进程程序 set follow-fork-mode child 设置GDB调试子进程 set follow-fork-mode parent 设置GDB调试父进…...

TDengine 时序数据的保留策略

“TDengine除vnode分片之外&#xff0c;还对时序数据按照时间段进行分区。每个数据文件只包含一个时间段的时序数据&#xff0c;时间段的长度由DB的配置参数days决定。这种按时间段分区的方法还便于高效实现数据的保留策略&#xff0c;只要数据文件超过规定的天数&#xff08;系…...

Java-多线程解析1

一、线程的描述&#xff1a; 1、线程是一个应用程序进程中不同的执行路径比例如&#xff1a;一个WEB服务器&#xff0c;能够为多个用户同时提供请求服务&#xff1b;而 -> 进程是操作系统中正在执行的不同的应用程序,比如&#xff1a;我们可以同时打开系统的word和游戏 2、多…...

PHP 判断用户当前坐标是否在电子围栏内

可以使用射线法判断用户当前坐标点是否在电子围栏内。 具体步骤如下&#xff1a; 1. 将电子围栏的四个角坐标按顺序连接成一个封闭多边形。 2. 从用户当前坐标点向外发射一条射线&#xff0c;判断这条射线与多边形的交点个数。 3. 如果交点个数为奇数&#xff0c;则用户当前…...

Java版本工程管理系统源码企业工程项目管理系统简介

一、立项管理 1、招标立项申请 功能点&#xff1a;招标类项目立项申请入口&#xff0c;用户可以保存为草稿&#xff0c;提交。 2、非招标立项申请 功能点&#xff1a;非招标立项申请入口、用户可以保存为草稿、提交。 3、采购立项列表 功能点&#xff1a;对草稿进行编辑&#x…...

高速缓存(cache)的原理: 了解计算机架构与性能优化

计基之存储器层次结构 Author&#xff1a; Once Day Date&#xff1a; 2023年5月9日 长路漫漫&#xff0c;而今才刚刚启程&#xff01; 本内容收集整理于《深入理解计算机系统》一书。 参看文档: 捋一捋Cache - 知乎 (zhihu.com)iCache和dCache一致性 - 知乎 (zhihu.com)C…...

【Vue3+TS项目】硅谷甄选day04--顶部组件搭建+面包屑+路由鉴权

顶部组件搭建 顶部左侧折叠和面包屑实现 左侧菜单刷新折叠的问题解决---属性default-active 折叠之后图标不见&#xff1a;icon放在插槽外面----element的menu属性&#xff1a;collapse project\src\layout\index.vue // 获取路由对象 import { useRoute } from vue-route…...

某oa 11.10 未授权任意文件上传

漏洞简介 之前也对通达 oa 做过比较具体的分析和漏洞挖掘&#xff0c;前几天看到通达 oa 11.10 存在未授权任意文件上传漏洞&#xff0c;于是也打算对此进行复现和分析。 环境搭建 https://www.tongda2000.com/download/p2019.php 下载地址 &#xff1a;https://cdndown.tongda…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

针对药品仓库的效期管理问题,如何利用WMS系统“破局”

案例&#xff1a; 某医药分销企业&#xff0c;主要经营各类药品的批发与零售。由于药品的特殊性&#xff0c;效期管理至关重要&#xff0c;但该企业一直面临效期问题的困扰。在未使用WMS系统之前&#xff0c;其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...

倒装芯片凸点成型工艺

UBM&#xff08;Under Bump Metallization&#xff09;与Bump&#xff08;焊球&#xff09;形成工艺流程。我们可以将整张流程图分为三大阶段来理解&#xff1a; &#x1f527; 一、UBM&#xff08;Under Bump Metallization&#xff09;工艺流程&#xff08;黄色区域&#xff…...