C++——类和对象(1)
1. 类
我们之前提及过C语言是面向过程的语言,其解决问题的方式是关注问题过程,然后逐步解决。而C++是面向对象编程,聚焦于对象,依靠多个对象之间的交互关系解决问题。而类这个概念的引入则是面向对象的最深刻体现。
1.1 C++中的结构体
C++兼容C,所以C++的结构体完全涵盖了C语言中结构体的语法形式。除此之外,C++结构体也做出了一些改进,如定义结构体变量不再一定需要struct关键字,不过最大的变化还是体现在结构体内可以定义函数了。
在结构体内定义的函数可以直接使用结构体中的成员变量,在调用成员函数时可以直接使用成员访问的方式就行调用,函数中的成员变量则会自动被替换为调用结构体变量对应的结构体变量。
struct Stack {//C++的结构体内既可以定义变量,也可以定义函数//变量int* _arr;int _capacity;int _top;//函数void Init(int capacity = 4){_arr = (int*)malloc(sizeof(int) * capacity);if (_arr == nullptr){perror("malloc fail");return;}_capacity = capacity;_top = 0;}
};
int main()
{//定义结构体变量可以不加structstruct Stack st1;Stack st2;//调用成员函数st1.Init();st2.Init(8);
}
需要注意的是成员变量的命名,尽量加入一些标识使得可以很容易分辨出是一个成员变量,以防在成员函数中调用产生分不清的情况。类的成员变量命名也要注意这一点。
1.2 C++的类
但是在C++中我们一般使用类来替代结构体,类的关键字为class。
1.2.1 类的定义
1.2.1.1 声明和定义全部放在类体中
声明和定义同时放在类体中,这种方式比较简便,就像C语言阶段的声明定义不分离一样。
class Date
{int _year;int _month;int _day;void Show(){cout << _year << '-' << _month << '-' << _day << endl;}
};
1.2.1.2 声明放在类的头文件,定义放在类的实现文件
这种方法类似于C语言中的声明和变量分离,比较规整并且便于合作开发。
这种方法需要注意类的作用域,即需要 类名::成员名 来指明成员所属的类域。
date.h
#pragma once class Date {int _year;int _month;int _day;void Show(); };date.cpp
#include"date.h" void Date::Show() {cout << _year << '-' << _month << '-' << _day << endl; }
1.2.2 类的访问限定符
1.2.2.1 封装
面向对象有三大特性:封装、继承、多态。
封装指的是将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。在C++中可以借助访问限定符,来控制哪些成员或方法可以在类外部使用,从而实现封装的特性。
1.2.2.2 访问限定符
C++的访问限定符有三个:public(公有),protected(保护),private(私有)。这三个访问限定符只有public修饰的成员支持在类外被访问,而protected和private是不可以的。
访问限定符在C++中的形式是访问限定符带一个冒号。其限定范围是自符号起到下一个访问限定符或类结束为止。
class成员的默认访问权限是private,struct成员的默认访问权限是public。
struct Stack {int* _arr;int _capacity;int _top;void Init(int capacity = 4){_arr = (int*)malloc(sizeof(int) * capacity);if (_arr == nullptr){perror("malloc fail");return;}_capacity = capacity;_top = 0;}
private:void Show(){}
};
class Date
{int _year;int _month;int _day;public:void Init(int year = 2000, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Show(){cout << _year << '-' << _month << '-' << _day << endl;}
};int main()
{struct Stack st1;//struct默认访问权限是publicst1.Init();int a = st1._capacity;//st1.Show();//errorDate d1;//class默认访问权限是private//d1._year = 2024; //errord1.Init();d1.Show();
}
1.2.3 类的实例化
类和结构体在一定程度上是相似的。在定义结构体或类的时候只是限定了有哪些成员,类似于给出图纸,但此时并没有在内存中分配空间。直到我们创建结构体变量或类对象,这时候才会在内存中开辟空间,我们才能正常访问使用。这一步就叫做类的实例化。
class Date
{int _year;int _month;int _day;public:void Init(int year = 2000, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Show(){cout << _year << '-' << _month << '-' << _day << endl;}
};int main()
{//Date.Init(); //error 没有实例化Date d1;d1.Init();
}
1.2.4 类的大小
类的大小计算方式与结构体相同。类中的成员函数不会存放在对象开辟的空间中,而是统一放在代码段中。所以类的大小只与成员变量有关而与成员函数无关。当类中没有成员函数时,编译器中会为这个空类对象分配一个字节的空间作为占位。
class C1
{int a;char c;double d;void func(){}
};
class C2
{void func(){}
};
class C3
{};int main()
{cout << sizeof(C1) << endl; //16cout << sizeof(C2) << endl; //1cout << sizeof(C3) << endl; //1
}
1.3 this指针
在了解了这么多后有一个问题,在调用成员函数时,我们并没有传递对象的相关信息,函数凭什么知道我们调用的对象是d1而不是d2呢?这是因为this指针发挥了作用。
在C++中,编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数这也就是我们所要介绍的this指针。函数调用时,this指针会指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量” 的操作,都是通过this指针去访问的。只不过所有的操作对用户是透明的,即用户不需要来传递,由编译器自动完成。
我们可以通过观察汇编代码发现这个隐藏的this指针传参。

class Date
{int _year;int _month;int _day;public://void Init(Date* const this, int year = 2000, int month = 1, int day = 1)void Init(int year = 2000, int month = 1, int day = 1) {this->_year = year;_month = month;_day = day;}//void Show(Date* const this)void Show(){cout << _year << '-' << _month << '-' << _day << endl;}
};
int main()
{Date d1;d1.Init(2024, 2, 25);d1.Show();
}
我们对this指针进行总结:
①this指针的类型是 类类型* const,这说明在函数成员内不可以修改this,但是修改通过this解引用的值。
②this指针只能在成员函数内使用。
③对象中并不储存this指针,在成员函数调用时将对象的地址作为实参传递给成员函数的this形参。
④this指针真实存在,但是传参是由编译器自动完成的,我们不可以在实参和形参位置显式写出this指针的传递。
⑤我们可以在成员函数内部使用this指针。this作为参数,存储在栈中。
class C
{
public:int _a;void func(){cout << "func()" << endl; //没有使用this指针,所以没有空指针解引用,不报错//cout << _a << endl; //error 实际上是this->_a,this是空指针,所以报错}
};
int main()
{C c1;C* pc = nullptr;pc->func(); //-> 不解引用,而是将pc作为参数传给this,this接收参数,值为nullptr(*pc).func(); //. 不解引用,也是将pc传给this指针,this接收参数,值为nullptr
}
在成员函数调用时,->或.两个操作符并不进行解引用,而是表示将传给this指针的对象是谁,所以在主函数中并未报错,在成员函数中访问成员变量时才会对this解引用。
相关文章:
C++——类和对象(1)
1. 类 我们之前提及过C语言是面向过程的语言,其解决问题的方式是关注问题过程,然后逐步解决。而C是面向对象编程,聚焦于对象,依靠多个对象之间的交互关系解决问题。而类这个概念的引入则是面向对象的最深刻体现。 1.1 C中的结构体…...
vue+element ui上传图片到七牛云服务器
本来打算做一个全部都是前端完成的资源上传到七牛云的demo,但是需要获取token,经历了九九八十一难,最终还是选择放弃,token从后端获取(springboot)。如果你们有前端直接能解决的麻烦记得私我哦!…...
学不动系列-git-hooks和husky+lintstage
git-hooks 为了保证提交的代码符合规范,可以在上传代码时进行校验。常用husky来协助进行代码提交时的eslint校验。husky是基于git-hooks来实现,在使用husky之前,我们先来研究一下git-hooks。 构建git-hooks测试项目 需要使用git-hooks就需…...
K8S相关小技巧《四》
需求: 我作为Kubernetes的集群管理员,前一段时间有收到一个需求,需要我创建一个受限访问的用户kubeconfig,提供给跳板机的某用户。 该kubeconfig需要在非Kubernetes节点的某跳板机上由指定的非root用户使用,该用户仅能…...
Delphi 报错 Type androidx.collection.ArraySet is defined multiple times
Delphi 11 建立一个新的 Multi-Device Application 编译成app的时候报错 报错信息 [PAClient Error] Error: E7688 Unable to execute "E:\Program\Java\jdk1.8.0_301\bin\java.exe" -cp "e:\program\embarcadero\studio\22.0\bin\Android\r8-3.3.28.jar"…...
Post请求中文乱码问题
url*************************************这里填写自己请求的网址 response requests.post(url, datajson.dumps(body),headersheader) r response.text print 打印乱码长这样: data:{“code”:0,“data”:{“end”:false,“message”:“{\n “ˆ—¡A”: [“…...
LeetCode -- 79.单词搜索
1. 问题描述 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水…...
单元测试、集成测试、系统测试有什么不同?
单元测试、集成测试和系统测试是软件测试开发中不可或缺的部分。 单元测试: 范围:单元测试是对软件中最小的可测试单元的测试,通常是函数、方法或类。 目的:它的目标是验证每个单独的单元是否按照预期工作,以增加代码…...
数据迁移DTS | 云上MySQL 数据库迁移至达梦数据库
引入 云上 MySQL 数据库 —> 向达梦国产化数据库迁移 下载&安装 达梦客户端工具 DM->可参考之前国产化专栏达梦文章 创建模式 在客户端分别依次执行以下命令脚本(这里没有通过客户端管理工具去创建达梦数据库的模式,当然也可以通过图形化界…...
Linux进程管理:(二)进程调度原语
文章说明: Linux内核版本:5.0 架构:ARM64 参考资料及图片来源:《奔跑吧Linux内核》 Linux 5.0内核源码注释仓库地址: zhangzihengya/LinuxSourceCode_v5.0_study (github.com) 进程调度的概念比较简单,…...
Compose 介绍
Compose 介绍 Android Compose 是 Google 官方推出的用于构建原生 Android UI 的现代工具包。它使用 Kotlin 语言编写,可以帮助开发人员更轻松、更快速地创建精美、响应式和高性能的 Android 应用。 Compose 的优势 声明式 UI: Compose 使用声明式 UI…...
5分钟搞定Python中函数的参数
函数的灵活性非常高,除了常规定义的位置参数以外,还支持默认参数、关键字参数、以及可变参数 ... 这样以来,不但能应对各种复杂的情况,甚至还可以简化调用者的代码。 位置参数 在调用函数时,一般会根据函数定义的参数…...
Gitlab: 私有化部署
目录 1. 说明 2. 资源要求 3. 安装 4. 配置实践 4.1 服务器 4.2 人员与项目 4.2 部署准备 4.2.1 访问变量及用户账号设置 4.2.2 Runner设置 4.2.3 要点 5. 应用项目 CI/CD 6. 参考 1. 说明 gitlab是一个强大且免费的代码管理/部署工具,能统一集成代码仓…...
深入理解Linux线程(LWP):概念、结构与实现机制(2)
🎬慕斯主页:修仙—别有洞天 ♈️今日夜电波:会いたい—Naomile 1:12━━━━━━️💟──────── 4:59 🔄 ◀️ ⏸ ▶️ ☰ &a…...
VBS脚本搞定,快速批量提取一堆Excel文件中的数据
1.需求诞生 小王就职于一家国有大型企业,工作业务十分繁忙,在处理企业某业务数据时,需要从上千个Excel文件中提取某一单元格位置的数据,并整理到另一个Excel文件。要说是这样的Excel文件仅有几个或者十几个也还好,手动…...
大数据分析案例-基于SVM支持向量机算法构建手机价格分类预测模型
🤵♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞Ǵ…...
WPF 滑动条样式
效果图: 浅色: 深色: 滑动条部分代码: <Style x:Key"RepeatButtonTransparent" TargetType"{x:Type RepeatButton}"><Setter Property"OverridesDefaultStyle" Value"true"/&g…...
论文设计任务书学习文档|基于Web的个性化简历职位推荐系统的设计与实现
文章目录 论文(设计)题目:基于Web的个性化简历职位推荐系统的设计与实现1、论文(设计)的主要任务及目标2、论文(设计)的主要内容3、论文(设计)的基本要求4、进度安排论文(设计)题目:基于Web的个性化简历职位推荐系统的设计与实现 1、论文(设计)的主要任务及目标…...
Win11系统安装安卓子系统教程
随着Win11系统的不断普及,以及硬件设备的更新换代,我相信很多同学都已经更新并使用到了最新的Win11系统。那么,Win11系统最受期待的功能“Windows Subsystem for Android”(简称WSA),即《安卓子系统》。他可…...
Python实现双向链表:从基础到应用
一、引言 双向链表是一种比单向链表更复杂的数据结构,每个节点除了包含数据和指向下一个节点的指针外,还包含一个指向前一个节点的指针。这种结构使得我们可以从链表的任何节点开始,向前或向后遍历链表。 目录 一、引言 二、节点定义 三、…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
DAY 26 函数专题1
函数定义与参数知识点回顾:1. 函数的定义2. 变量作用域:局部变量和全局变量3. 函数的参数类型:位置参数、默认参数、不定参数4. 传递参数的手段:关键词参数5 题目1:计算圆的面积 任务: 编写一…...
