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

C++类与对象 (上)

目录

前言:

类和对象的理解

类的引入

类的定义与使用方式

访问限定符

类的两种定义方式

成员变量的命名规则

类的作用域

类的实例化

类对象模型

计算类对象的大小

类对象的存储方式

this指针


前言:

  • C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题;
  • C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成;

类和对象的理解

是一个抽象的概念,描述了一类对象的共同属性行为

对象是类的具体化,它是类的实例,具有类中定义的属性和行为;

在C++中,通常由数据成员成员函数组成,数据成员是类的属性,它们描述了对象的状态,成员函数是类的行为,它们描述了对象可以执行的操作,对象的创建是通过类的实例化来完成的,当程序需要使用类时,可以通过创建类的对象来使用类的属性和行为;

举例如下:

将“汽车”看作一个类,在这个类中定义了汽车的属性和行为,比如颜色、品牌、速度等属性,以及加速、刹车、转弯等行为;当我们要描述具体一辆汽车时,就需要创建一个该类的对象,并根据需要设置其相应的属性值或对其进行行为操作;

类的引入

由于C++兼容C语言中struct的所有用法,同时C++对关键字struct进行了升级,将struct升级为类;

  •  struct    类名 (类名即为变量类型)
//c语言
struct Stack
{int* a;int top;int capacity;
};
int main()
{//Stack s1; //C语言 ---> 未定义的标识符struct Stack s1;//只能采取带上struct关键字定义变量return 0;
}
//c++ 
struct Stack
{int* a;int top;int capacity;
};
int main()
{Stack s1;//可直接采取这种方案定义变量,不需要加上struct的关键字return 0;
}
//c语言定义链表结点
struct ListNode
{//ListNode* next;//C语言 ---> 未定义的标识符struct ListNode* next;int val;
};
//c++定义链表结点
struct ListNode
{ListNode* next;//编译通过int val;
};
  • C++结构体中可以定义函数;
//c++ 类里面可以定义函数
struct Stack
{int* a;int top;int capacity;//初始化栈void Init(){a = 0;top = 0;capacity = 0;}
};

 C++用关键字 class 代替 struct;

类的定义与使用方式

class 类名
{//类体: 由成员变量与成员函数组成}; //此处分号不可省略

类的成员:类中的变量称为类的属性或成员变量类中的函数称为类的方法或成员函数

访问限定符

C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用;

 访问限定符说明:

  1. public修饰的成员类外可以直接被访问
  2. protected和private修饰的成员类外不能直接被访问(此处protected和private是类似的)
  3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止;
  4. 如果后面没有访问限定符,作用域就到 } 即类结束;
  5. class的默认访问权限为privatestruct默认访问权限为public(因为struct要兼容C)
class Stack
{
private:int* a;int top;//a,top,capacity--->成员变量私有int capacity;//private的作用域从private开始到public,若没有public,直接到类结束;//由于class的默认访问权限为私有,省略掉private,三个成员变量依旧私有
public://初始化栈void Init()// Init()函数公有{a = 0;  top = 0;capacity = 0;}
}; //类结束

类定义的惯例:成员变量私有,成员函数公有;

class Stack
{
public:int* a;int top;int capacity;//初始化栈void Init(){a = 0;  top = -1;capacity = 0;}//空栈的判断bool StackEmpty(){return (top == -1);}
}; 
int main()
{Stack s1;s1.Init();//判断方式1:空栈, 若top=0,表示指向栈顶元素的下一个位置;//         空栈, 若top=-1,表示指向栈顶元素的位置;//栈的定义方式不同,如下判断方法可能导致出错;if (s1.top==0)//判断方式2:采取访问成员函数进行判断,直接调用判空函数,不会出错if (!s1.StackEmpty()){}//如上就是成员变量私有,成员函数公有的原因return 0;
}

类的两种定义方式

定义方式1:类的声明放在.h文件中,成员函数定义放在.cpp文件中;

                    (注:成员函数名前加 类名 ::)

定义方式2:声明和定义全部放在类体中;

                  (注:成员函数如果在类中定义编译器可能会将成员函数当成内联函数处理)

成员变量的命名规则

class Date
{
public:void Init(int year,int month,int day){// 这里的year到底是成员变量,还是函数形参?year = year;//局部优先,year为函数形参//局部优先是指在函数内部创建了一个和全局变量同名的局部变量时;//函数内部对该变量的操作会优先作用于局部变量,而不会改变全局变量的值}
private:int year;int month;int day;
};

为了避免如上情形,C++采用成员变量前加 _

class Date
{
public:void Init(int year,int month,int day){_year = year;}
private:int _year;int _month;int _day;//year month day成员变量前加 _
};

类的作用域

定义了一个 新的作用域类的所有成员都在类的作用域中
类体外定义成员时,需要使用 ::作用域限定符指明成员属于哪个 类域
c++中由{ }所定义的皆为作用域;
class Stack
{//变量的声明,没有在内存中开辟空间int* a;int top;int capacity;
public:void Init();bool StackEmpty();
};
//需要指定Init()函数属于Stack类域
void Stack::Init()
{a = 0;top = 0;capacity = 0;
}

类的实例化

用类的类型创建对象的过程,称为类的实例化;
  1. 类是对对象进行描述的是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它;
  2. 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量
class Date
{
public:void Init(int year,int month,int day){_year = year;}int _year;int _month;int _day;
};
int main()
{Date::_year = 2023;//编译错误,成员变量为声明,没有开辟内存空间存储;// Date d; d.year=2023  //正确做法return 0;
}
//Date类是没有空间的,只有Date类实例化出的对象才有具体的年份

3. 类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间

类对象模型

类对象模型:类对象模型是指将类的成员函数和成员变量存储在一起的方式,这种方式将类的成员函数和成员变量封装在一个对象中,通过该对象来访问类的成员;

计算类对象的大小

# include <iostream>
using namespace std;
class Date
{
public:void Init(int year,int month,int day){_year = year;}int _year;int _month;int _day;
};
int main()
{Date d;cout << sizeof(d) << endl;return 0;
}
问题:类中既可以有成员变量,又可以有成员函数,那么一个类的对象中包含了什么?如何计算一个类的大小?

类对象的存储方式

类对象的存储方式:

对象中只保存成员变量,成员函数存放在公共代码段,这种方式将类的成员变量存储在对象中,而将成员函数存放在公共代码段中,通过对象来访问类的成员函数;

结论:一个类的对象大小,实际就是该类中”成员变量”之和,注意考虑内存对齐 ;

空类的大小:空类的大小为1字节;即使一个类没有任何成员变量和成员函数,它也会占用1字节的内存空间;

空的结构体大小:空的结构体大小为0字节,与空类不同,空的结构体不占用任何内存空间;

//类中仅有成员函数--->1byte
//对象中无成员函数
class B
{
public:void f2() {}
};
int main()
{B b;cout << sizeof(b) << endl;return 0;
}
//空类的大小 ---> 1byte
//无成员变量的类开辟1个字节,该字节不存储有效数据
//标识定义的对象存在过
class C
{};
int main()
{C c;cout << sizeof(c) << endl;return 0;
}

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(2023, 12, 17);d2.Init(2023, 12, 16);d1.Print();d2.Print();return 0;
}

运行结果:

Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,d1调用的Print()函数与d2调用的Print()函数相同,那当d1调用Print()函数时,该函数是如何知道应该显示d1对象,而不是显示d2对象呢?
C++ 中通过引入 this指针 解决该问题,即: C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量” 的操作,都是通过该指针去访问;只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成

this指针的特性:

  1. this指针的类型类型* const 由于const修饰this,this指针不允许被修改;
  2. 只能在“成员函数”的内部使用 (不能显示的写实参和形参,但是可以在类中显示的使用);
  3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参,所以对象中不存储this指针
  4.  this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递

相关文章:

C++类与对象 (上)

目录 前言&#xff1a; 类和对象的理解 类的引入 类的定义与使用方式 访问限定符 类的两种定义方式 成员变量的命名规则 类的作用域 类的实例化 类对象模型 计算类对象的大小 类对象的存储方式 this指针 前言&#xff1a; C语言是面向过程的&#xff0c;关注的是过…...

no module named ‘xxx‘

目录结构如下 我想在GCNmodel的model里引入layers的GraphConvolution&#xff1a;from GCNmodel.layers import GraphConvolution&#xff0c;但这样却报错no module named GCNmodel&#xff0c;而且用from layers import GraphConvolution也不行。然后用sys.path.appen(xxx)…...

Go实现MapReduce

背景 当谈到处理大规模数据集时&#xff0c;MapReduce是一种备受欢迎的编程模型。它最初由Google开发&#xff0c;用于并行处理大规模数据以提取有价值的信息。MapReduce模型将大规模数据集分解成小块&#xff0c;然后对这些小块进行映射和归约操作&#xff0c;最终产生有用的…...

Axure的交互样式和情形

Axure的交互样式和情形 交互样式 Axure是一个流行的原型设计工具&#xff0c;它允许您创建交互式原型&#xff0c;模拟应用程序或网站的功能和用户界面。在Axure中&#xff0c;您可以设置各种交互样式来使原型更加生动和真实。 链接触发器&#xff1a;通过给一个元素添加链接…...

Mybatis在新增某个数据后,如何获取新增数据的id

在某些业务中&#xff0c;我们在新增一条数据之后&#xff0c;需要拿到这条数据的id来对这条数据进行后续的一个操作&#xff0c;如何拿取id呢&#xff1f; 使用的是<insert> 中的useGeneratedKeys 和 keyProperty 两个属性 1.在Mybatis Mapper文件中添加属性 “useGene…...

12.4~12.14概率论复习与相应理解(学习、复习、备考概率论,这一篇就够了)

未分配的题目 概率计算&#xff08;一些转换公式与全概率公式&#xff09;与实际概率 &#xff0c;贝叶斯 一些转换公式 相关性质计算 常规&#xff0c;公式的COV与P 复习相关公式 计算出新表达式的均值&#xff0c;方差&#xff0c;再套正态分布的公式 COV的运算性质 如…...

关于多重背包的笔记

多重背包可以看作01背包的拓展&#xff0c; 01背包是选或者不选。多重背包是选0个一直到选s个。 for (int i 1; i < n; i) {for (int j m; j > w[i]; --j){f[j] max(f[j], f[j - 1*w[i]] 1*v[i], f[j - 2*w[i]] 2*v[i],...f[j - s*w[i]] s*v[i]);} } 由上述伪代码…...

如何使用 Java 的反射

如何使用 Java 的反射&#xff1f; 通过一个全限类名创建一个对象 Class.forName(“全限类名”); 例如&#xff1a;com.mysql.jdbc.Driver Driver 类已经被加载到 jvm 中&#xff0c;并且完成了类的初始化工作就行了 类名.class; 获取 Class<&#xff1f;> clz 对象对…...

PLC-Recorder V3 修改服务器和客户端通讯端口的方法

PLC-Recorder V3是服务器和客户端的架构&#xff0c;他们之间用TCP通讯。如果客户端无法与服务器建立连接&#xff08;重启也无效&#xff0c;并且确保没有老版本的PLC-Recorder在运行&#xff09;&#xff0c;则可能是端口被占用了。这时候需要修改他们之间的通讯端口&#xf…...

libevent服务GET/POST的简单使用

目录 1、前言2、测试demo2.1、目录结构2.2、 测试源码2.2.1、http_server.cpp2.2.2、 http_server.h 2.3、 编译2.4、 运行结果2.4.1、测试POST2.4.2 、测试GET请求 1、前言 项目开发中经常需要使用到私有协议和Qt,Android等GUI前端通信&#xff0c;比较常用的使用POST和GET方式…...

MySQL 系列:注意 ORDER 和 LIMIT 联合使用的陷阱

文章目录 前言背后的原因ORDER BY 排序列存在相同值时返回顺序是不固定的LIMIT 和 ORDER BY 联合使用时的行为ORDER BY 或 GROUP BY 和 LIMIT 联合使用优化器默认使用有序索引 如何解决其它说明个人简介 前言 不知道大家在在分页查询中有没有遇到过这个问题&#xff0c;分页查…...

通过实例理解OAuth2授权

在之前的《通过实例理解Go Web身份认证的几种方式[1]》和《通过实例理解Web应用授权的几种方式[2]》两篇文章中&#xff0c;我们对Web应用身份认证(AuthN)和授权(AuthZ)的几种方式做了介绍并配以实例增强理解。 在现实世界中&#xff0c;还有一大类的认证与授权是在前面的文章中…...

MATLAB2022安装下载教程

安装包需从夸克网盘自取&#xff1a; 链接&#xff1a;https://pan.quark.cn/s/373ffc9213a1 提取码&#xff1a;N7PW 1.将安装包解压 2.以管理员的身份运行文件夹中的setup文件 3.点击高级选项--->我有文件安装密钥 4. 选择【是】&#xff0c;进入下一步 5.输入密钥 0532…...

从零开始搭建Go语言开发环境

https://www.liwenzhou.com/posts/Go/install_go_dev/ “go 命令现在默认在模块感知模式下构建包&#xff0c;即使没有 go.mod 存在也是如此。 “您可以将 GO111MODULE 设置为 auto&#xff0c;仅当当前目录或任何父目录中存在 go.mod 文件时&#xff0c;才能启用模块感知模式…...

vite+vue3+ts+tsx+ant-design-vue项目框架搭建

参与公司项目开发一段时间了&#xff0c;项目用到了很多新的技术&#xff08;vite,vue3,ts等等&#xff09;&#xff0c;但是框架都是别人搭好的&#xff0c;然后就想说如果是自己的话&#xff0c;会从零搭建一个吗&#xff0c;于是就有了这篇文章。 目录 一、涉及到的相关依…...

【5G PHY】5G小区类型、小区组和小区节点的概念介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…...

创建个人网站(一)从零开始配置环境,搭建项目

目录 前言配置环境前端后端遇到的问题1.安装了nvm和node&#xff0c;vscode没反应2.安装完脚手架之后vue指令不存在 vscode插件&#xff08;以后遇到好的会添进去&#xff09; 前言 从刚开始学前端的html直到现在前后端都有在开发&#xff0c;我一直都有一个想法&#xff0c;就…...

fripside - promise lrc

[ti:promise] [ed:2] [rt:20] [ml:0|0] [00:05.172]words:Satoshi Yaginuma, Shinichiro Yamashita [00:09.664]music&arrangement:Satoshi Yaginuma, Shigetoshi Yamada [00:14.565]PCゲーム「ENGAGE LINKS」 (Alcot) エンディングテーマ [00:20.000] [00:46.442]朝の陽射…...

网络连接和协议

网络连接是通过一系列协议来实现的&#xff0c;其中TCP/IP协议和HTTP协议是其中两个关键的协议。 1. **TCP/IP协议&#xff1a;** - TCP/IP&#xff08;Transmission Control Protocol/Internet Protocol&#xff09;是一组用于在互联网上传输数据的协议。它是一个层次化的…...

MySQL数据库,表的增量备份与恢复

1. 从物理与逻辑的角度 数据库备份可以分为物理备份和逻辑备份。物理备份是对数据库操作系统的物理文件&#xff08;如数据 文件&#xff0c;日志文件等&#xff09;的备份。这种类型的备份适用于在出现问题时需要快速恢复的大型重要数据库。 物理备份又可以分为冷备份&#xf…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

比较数据迁移后MySQL数据库和OceanBase数据仓库中的表

设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构

React 实战项目&#xff1a;微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇&#xff01;在前 29 篇文章中&#xff0c;我们从 React 的基础概念逐步深入到高级技巧&#xff0c;涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...

C++中vector类型的介绍和使用

文章目录 一、vector 类型的简介1.1 基本介绍1.2 常见用法示例1.3 常见成员函数简表 二、vector 数据的插入2.1 push_back() —— 在尾部插入一个元素2.2 emplace_back() —— 在尾部“就地”构造对象2.3 insert() —— 在任意位置插入一个或多个元素2.4 emplace() —— 在任意…...