c++阶梯之类与对象(一)

目录

 1.面向过程与面向对象

c语言的视角:

c++的视角 

2. 类的引入 

3. 类的定义 

3.1 类的两种定义方式

3.2 成员变量如何命名

4. 类的访问限定符与封装

4.1 访问限定符 

4.2 封装

5. 类的作用域

6. 类的实例化 

7. 类对象模型 

7.1 怎么计算一个类对象的大小 

7.2 类对象存储的方式

7.3 结构体内存对齐规则

8. this指针

8.1 this指针的引出 

8.2 this指针的特性 

结语


 1.面向过程与面向对象

c语言与c++分别是面向过程与面向对象的拥护者。

<  > c语言是面向过程的,关注的是解决问题的过程,分解求解步骤,通过函数调用逐步解决问题。

<  > C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。

我们来看看同一事件在面向过程与面向对象的眼里究竟是怎样的。以洗衣服为例。 

c语言的视角:

c++的视角 

2. 类的引入 

在c语言中,自定义类型(struct结构体)只能定义变量,但在c++中,结构体不但能定义变量,还能定义函数。

在c++中,将结构体称为类,其关键字为class,但同时兼容c语言的struct ,它们之间的区别在后面会讲到。

3. 类的定义 

class className
{
// 类体:由成员函数和成员变量组成
}; // 一定要注意后面的分号

class是c++定义类的关键字,className是类的名字,{ } 为类的主体。注意:{ } 后的分号。

{ } 中的内容称为类的成员,其内定义的变量称为类的属性或成员变量,函数则称为方法或成员函数。 

3.1 类的两种定义方式

1.声明与定义全部放入类体内 (如果函数定义在类内,则编译器有可能将函数当作内联函数处理) 。

2. 声明与定义分离,声明在类内放入 .h 文件,定义在类外放入 .cpp 文件。 

我们上代码来看看

//声明与定义全部放在类体内
class Person
{
public:void ShowInfo(){cout << "name: " << _name << "age: " << _age << endl;}char* _name;int _age;
};

这里声明与定义分离为了方便,我将他们定义在了同一文件内。 

//声明与定义分离
class Person
{
public:void ShowInfo();char* _name;int _age;
};
#include"Person.h"
void Person::ShowInfo()
{cout << "name: " << _name << "age: " << _age << endl;
}

注意下图中圈出来的地方,成员函数定义在类外时需要在函数名前用域作用符连接类名。

3.2 成员变量如何命名

我们看下面这段有关日期类的代码

class Date
{
public:void Init(int year, int month, int day){year = year;month = month;day = day;}int year;int month;int day;
};

这种代码不仅可读性差,还可能会造成歧义,因此一般建议成员变量的命名要与正常变量名做区别,比如在成员变量名前加_或m_。代码如下:

class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}int _year;int _month;int _day;
};

4. 类的访问限定符与封装

c++实现封装的方式:用类将对象的属性与方法结合在一起,通过访问权限选择性的将其接口提供给外部使用。

那么是如何实现访问限定的呢?

这个就要靠访问限定符了。 

4.1 访问限定符 

【访问限定符说明】
1. public修饰的成员在类外可以直接被访问
2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4. 如果后面没有访问限定符,作用域就到 } 即类结束。
5. class的默认访问权限为private,struct为public(因为struct要兼容C)
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别 

在这里我们就可以解答struct与class区别的问题了。

C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来
定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类默认访问权限是private。注意:在继承和模板参数列表位置,struct和class也有区别,后序给大家介绍。

4.2 封装

面向对象有三大特性:封装、继承和多态。当然,并不代表只有这三大特性哦。

我们先来学习封装,那么什么是封装呢?

封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。封装本质上是一种管理,让用户更方便使用类。

比如:对于电脑这样一个复杂的设备,提供给用户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互,完成日常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件

对于计算机使用者而言,不用关心内部核心部件,比如主板上线路是如何布局的,CPU内部是如何设计的等,用户只需要知道,怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可
在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。

5. 类的作用域

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

 比如下面这段代码:

class Person
{
public:Person(char* name,int age=10){_name = name;_age = age;}void showinfo();
private:char* _name;int _age;
};void Person::showinfo()
{cout << _name << " " << _age << endl;
}int main()
{char name[] = "张三";Person zs(name, 20);zs.showinfo();return 0;
}

这里需要用域作用符指明类域。 

6. 类的实例化 

用类类型创建对象的过程,称为类的实例化
< 1 >. 类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它;
< 2 >. 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量Person类是没有空间的,只有Person类实例化出的对象才有具体的年龄。

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

7. 类对象模型 

7.1 怎么计算一个类对象的大小 

class A
{
public:A(int a = 10, int b = 20){_a = a;_b = b;}
private:int _a;int _b;
};

我们可以看到,在A类中,既有成员变量也有成员函数,那么我们要怎样计算他的大小呢?

7.2 类对象存储的方式

我们用下面的代码做一个实验,来看看类对象是怎么存储的。 

class C//只有成员变量
{
private:int _f;int _y;
};class D//空类
{};class E//只有成员函数
{
public:void showinfo(){cout << "D" << endl;}
};
int main()
{cout << "sizeof(C):" << sizeof(C) << endl;cout << "sizeof(D):" << sizeof(D) << endl;cout << "sizeof(E):" << sizeof(E) << endl;return 0;
}

由此可见:一个类的大小,实际就是该类中”成员变量”之和,当然要注意内存对齐
注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。

那么对象是如何调用成员函数的呢?

答案就是:成员函数保存在公共的代码段内,谁有需求谁就调用。

7.3 结构体内存对齐规则

1. 第一个成员在与结构体偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。VS中默认的对齐数为8。
3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍

这一点与c语言结构体对齐内容相同,有需要的朋友可以看我的这篇文章。

结构体的相关知识icon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/133279934

8. this指针

8.1 this指针的引出 

我们先简单实现一个日期类

class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void showinfo(){cout << _year << "/" << _month << "/" << _day  << endl;}private:int _year;int _month;int _day;
};int main()
{Date d1;d1.Init(2024, 2, 1);d1.showinfo();Date d2;d2.Init(1997, 1, 1);d2.showinfo();return 0;
}

 在上面日期类代码中,我们实现了两个对象的初始化与打印操作。那么问题来了,我们可以看到,Init() 与 showinfo() 两个函数并没有传入对象的参数,那么函数是怎样分辨出应该对哪个对象进行操作呢?

C++中通过引入this指针解决该问题:

C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

 

8.2 this指针的特性 

1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。
2. 只能在“成员函数”的内部使用
3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给
this形参。所以对象中不存储this指针。
4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过寄存器自动传
递,不需要用户传递 。

结语

都看到这里了,奖励自己看个段子吧!

欢迎大佬们指正!

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

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

相关文章

redis布隆过滤器(Bloom)详细使用教程

文章目录 布隆过滤器1. 原理2. 结构和操作3. 特点和应用场景4. 缺点和注意事项 应用-redis插件布隆过滤器使用详细过程安装以及配置springboot项目使用redis布隆过滤器下面是布隆过滤器的一些基础命令 扩展 布隆过滤器 Bloom 过滤器是一种概率型数据结构&#xff0c;用于快速判…

CUDA/TensorRT部署知识点

CUDA相关: 1、CUDA核函数嵌套核函数的用法多吗? 答:这种用法非常少,主要是因为启动一个kernel本身就有一定延迟,会造成执行的不连续性。 2、如下代码里的 grid/block 对应硬件上的 SM 的关系是什么? 答:首先需要理解grid/block是软件层的概念,而SM是硬件层的概念。所…

springboot151基于web的人力资源管理系统的设计与实现

人力资源管理系统的设计与实现 摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;员工信息因为其管理内容繁杂&#xff0c;管理数量繁…

SSH免密切换服务器案例-ssh协议(公钥和私钥)

公钥和私钥理解 公钥提供加密&#xff0c;私钥解密&#xff0c;公钥可以共享&#xff0c;私钥不可以。举例公钥相当于锁头&#xff0c;可以给别人用&#xff0c;钥匙相当于私钥&#xff0c;只能开自己发出去的锁头&#xff0c;也就是私钥和公钥成对&#xff0c;私钥只能解密对…

~小青蛙跳台阶~C语言~刷题

引言 这次&#xff0c;我们要与一只活泼可爱的小青蛙合作&#xff0c;并引导它跳台阶。小青蛙的体力十分充沛&#xff0c;尤其喜欢跳跃&#xff0c;让它作为我们的助手&#xff0c;来看看有几种跳跃指定台阶数的方法。 本文会涉及到函数递归的知识&#xff0c;后续我会更新讲解…

清华系2B模型杀出,性能吊打LLaMA-13B

2 月 1 日&#xff0c;面壁智能与清华大学自然语言处理实验室共同开源了系列端侧语言大模型 MiniCPM&#xff0c;主体语言模型 MiniCPM-2B 仅有 24 亿&#xff08;2.4B&#xff09;的非词嵌入参数量。 在综合性榜单上与 Mistral-7B 相近&#xff0c;在中文、数学、代码能力表现…

基于深度卷积神经网络的图像配准(DeepSlice)

文章目录 一、基于DeepSlice的切片配准1.1、研究现状1.2、网络模型&#xff08;DeepSlice&#xff09;1.3、优化策略1.3.1、开发了一个基准数据集&#xff08;GT&#xff09;1.3.2、构建了阶段二的训练数据集&#xff08;增强训练&#xff09;1.3.3、角度集成 切割索引&#x…

【Linux】统信服务器操作系统V20 1060a-AMD64 Vmware安装

目录 ​编辑 一、概述 1.1 简介 1.2 产品特性 1.3 镜像下载 二、虚拟机安装 一、概述 1.1 简介 官网&#xff1a;统信软件 – 打造操作系统创新生态 统信服务器操作系统V20是统信操作系统&#xff08;UOS&#xff09;产品家族中面向服务器端运行环境的&#xff0c;是一款…

Linux驱动 SPI子系统

1、SPI协议 SPI&#xff08;Serial Peripheral Interface&#xff09;是一种同步串行数据通信协议&#xff0c;通常用于连接微控制器和外部设备&#xff0c;如传感器、存储器、显示器等。SPI协议使用四根线进行通信&#xff0c;包括时钟线&#xff08;SCLK&#xff09;、数据输…

CSS要点总结

一、CSS 快速入门 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>css 快速入门</title><!-- 解读1. 在 head 标签内&#xff0c;出现了 <style type"text/css"></style…

Redis 的持久化机制是什么?各自的优缺点?

Redis 提供两种持久化机制 RDB&#xff08;默认&#xff09; 和 AOF 机制: RDB&#xff1a;是Redis DataBase缩写快照 RDB是Redis默认的持久化方式。按照一定的时间将内存的数据以快照的形式保存到硬盘中&#xff0c;对应产生的数据文件为dump.rdb。通过配置文件中的save参数来…

ChatLaw:基于LLaMA微调的法律大模型

文章目录 动机数据组成模型框架模型评估 北大团队发布首个的中文法律大模型落地产品ChatLaw&#xff0c;为大众提供普惠法律服务。模型支持文件、语音输出&#xff0c;同时支持法律文书写作、法律建议、法律援助推荐。 github地址&#xff1a;https://github.com/PKU-YuanGroup…

备份RK35XX 设备的ubuntu根文件系统的方法

简介 我们使用 RK35XX 提供的SDK包制作了一个完整的 ubuntu 镜像,烧录到设备中,会在设备中安装很多我们需要的软件,运行的一些自己写的脚本和业务程序,当我们有很多台设备时,不可能每台都一个个去安装,此时我们就需要一个工具来备份当前设备的根文件系统,然后再放到 SD…

2023年上-未来几年我要做什么

1月份&#xff0c;离职。 2月份&#xff0c;春节休假回来&#xff0c;中旬去参加了一个月的瑜伽培训&#xff0c;学会了倒立、鹤蝉。。。。 3月份&#xff0c;瑜伽培训结束&#xff0c;开始收拾房子&#xff0c;并调研各类项目。 4月份&#xff0c;参与了朋友的区块链项目 …

Leetcode—203. 移除链表元素【简单】

2024每日刷题&#xff08;一零九&#xff09; Leetcode—203. 移除链表元素 实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(n…

嵌入式linux移植篇之kernel

Linux的启动过程概述 Linux内核的启动过程是一个复杂而又有序的流程&#xff0c;涉及到硬件初始化、引导加载、内核初始化等多个步骤。以下是Linux内核的典型启动流程&#xff1a; BIOS/UEFI阶段&#xff1a; 电源启动&#xff1a;计算机通电后&#xff0c;BIOS&#xff08;…

#从零开始# 在深度学习环境中,如何用 pycharm配置使用 pipenv 虚拟环境

为Python项目创建虚拟环境 在深度学习环境和一般python环境中安装pipenv基本一致&#xff0c;只需要确认好pipenv指定的python版本即可,安装pipenv前&#xff0c;可以通过python --version来确认安装版本 快捷键&#xff1a;crtl alt S 查看interpreter&#xff0c;查看所有…

聊聊比特币----比特币地址

⽐特币地址是⼀个标识符&#xff08;帐号&#xff09;&#xff0c;包含27-34个字母数字拉丁字符&#xff08;0&#xff0c;O&#xff0c;I除外&#xff09;。地址可以以QR码形式表⽰&#xff0c;是匿名的&#xff0c;不包含关于所有者的信息。 地址⽰例&#xff1a;14qViLJfdG…

【51单片机】开发板和单片机的介绍(2)

前言 大家好吖&#xff0c;欢迎来到 YY 滴单片机系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过单片机的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

[Python] 什么是KMeans聚类算法以及scikit-learn中的KMeans使用案例

什么是无监督学习&#xff1f; 无监督学习是机器学习中的一种方法&#xff0c;其主要目的是从无标签的数据集中发现隐藏的模式、结构或者规律。在无监督学习中&#xff0c;算法不依赖于任何先验的标签信息&#xff0c;而是根据数据本身的特征和规律进行学习和推断。无监督学习…