类与对象(一)

news2024/11/18 11:23:36

目录

1 什么是面向过程和面向对象

1.1举例

2类的引入

3类的定义

3.1类的两种定义方式:

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

4.1访问限定符

4.1.1为什么要有访问限定符

4.1.2有哪些访问限定符呢?

 4.1.3简单举例理解

4.1.4C++中的class与struct的区别(面试问题)

 4.2封装

4.2.1什么是封装?(重要)

 5.类的作用域

 6.类的实例化

7. 类对象模型

7.1如何计算类对象的大小

7.2为什么空类的大小为1?

7.3函数在类里面的存储形式? 

7.4面试题

8.this指针

8.1this指针的引出

 8.2this指针的特性

8.3关于this指针的面试题

1. this指针存在哪里?

2. this指针可以为空吗? 

8.4思考:


1 什么是面向过程和面向对象

我们知道,c语言是一门面向过程的语言,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。而c++、Java则是一个面向对象的语言,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完 成。面向过程"和"面向对象"是两种不同的编程范式,它们反映了程序设计和组织代码的不同思想

面向过程

思想:面向过程编程的核心思想是将问题划分为一系列的步骤,每个步骤都是一个函数或者是一个子过程。程序的执行按照一些特定的步骤依次进行。

面向对象

思想:面向对象编程的核心是将程序看作是对象的集合,而不是一系列步骤的集合。对象是对数据和行为的封装,具有特定的属性和方法。

1.1举例

当我们将程序描述成洗衣服这一个事情。

对于面向过程的思想来说,我们将洗衣服的每一个子过程都列举出来:准备好要洗的衣服-->准备一个盆-->放水-->放衣服-->放洗服......

 对于面向对象的思想来说,我们先把整个事情划分成几个对象:人、衣服、洗衣机、洗衣粉

整个事情的过程:人将衣服丢进洗衣机、倒入洗衣粉、启动洗衣机

整个过程是由这些对象交互完成的,人不需要关心洗衣机是如何工作的

总结:不同的思想看待问题的角度不同,实现的方式也会有差别。选择面向过程还是面向对象通常取决于问题的性质和开发者的偏好。大多数现代编程语言支持两种范式,而实际的项目中通常会根据问题的需求灵活选择使用这两种范式。 

2类的引入

C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。比如: 之前在数据结构初阶中,用C语言方式实现的栈,结构体中只能定义变量;现在用C++方式实现, 会发现struct中也可以定义函数。

 

上面结构体的定义,在C++中更喜欢用class来代替。

3类的定义

类的定义和结构体很相似

class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。 类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者 成员函数

3.1类的两种定义方式:

1、声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。

2、类声明和成员函数定义分开。类声明放在.h的头文件中,类体里面也只有成员函数的声明,将成员函数定义在.cpp源文件中。为了防止命名冲突,这样定义的成员函数需要在前面加类的名称(类似命名空间声明)。

为了代码的维护性,一般用第二种类定义方式。

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

4.1访问限定符

4.1.1为什么要有访问限定符

对于一个类来说,也许会有很多的成员函数和成员属性,有些变量我们希望它能被外部直接访问,当然,大多数的变量我们都不希望外不能够直接访问,这样就太不安全了。所以我们需要使用访问限定符来划定属性和方法的访问权限,也便于我们对类的管理。

4.1.2有哪些访问限定符呢?

public(公有):使用 public 关键字标识,表示成员对外公开,可以在任何地方访问。这意味着类的外部代码可以直接访问公有成员

protected(保护):使用 protected 关键字标识,表示成员对于类的子类是可见的,但对于类的外部代码是私有的。

private(私有):使用 private 关键字标识,表示成员仅在类的内部可见,外部代码无法直接访问。私有成员只能在类的内部使用

说明:

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

如果后面没有访问限定符,作用域就到 } 即类结束。

class的默认访问权限为private,struct为public(因为struct要兼容C)。

访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别、

也就是说,访问限定符只是能否访问的一道门,通过这扇门后就不会管你了。

 4.1.3简单举例理解

定义以下类

外部访问public下的成员属性及方法,正常编译

外部访问private下的成员属性及方法,报错

4.1.4C++中的class与struct的区别(面试问题)

classstruct 之间的差异主要体现在默认的成员访问权限和继承方式上。除了这些,它们在语法上几乎是一样的

1、默认的成员访问权限:

  • class 中,默认的成员访问权限是 private
  • struct 中,默认的成员访问权限是 public

2、继承方式:

  • 通过 class 定义的派生类,默认的继承权限是 private
  • 通过 struct 定义的派生类,默认的继承权限是 public

对比两者我们可以发现,其实class和struct大致没有什么区别,class能做到的struct也能做到,只不过两者的默认权限有些差异,取决于具体的需求和编码风格。

 4.2封装

4.2.1什么是封装?(重要)

将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来 和对象进行交互。在实现封装时,通常使用访问修饰符来设置成员的访问权限。例如,使用 private 成员来隐藏内部细节,而通过 public 成员提供对外的接口

 举例

假设实现一个电脑类,开机键实现开机操作,对于用户来说无需在意开机的具体细节,只需要知道按下去就能开机开机键就是我们对外的接口。这样一来,用户能够更加方便的使用类,同样,避免了用户直接使用内部属性,提高了安全性

 5.类的作用域

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

 6.类的实例化

在面向对象编程中,类是一种模板或蓝图,对象是根据这个模板创建出来的具体实体。实例化是通过调用类的构造函数来创建对象的过程。用类类型创建对象的过程,称为类的实例化.

1. 类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没 有分配实际的内存空间来存储它

2. 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量

int main()
{
 Person._age = 100;   // 编译失败:error C2059: 语法错误:“.”
 return 0;
}

Person类是没有空间的,只有Person类实例化出的对象才有具体的年龄

7. 类对象模型

7.1如何计算类对象的大小

相对于c语言的结构体,c++的结构体可以在里面直接定义函数,这样一来有了函数的结构体的大小又怎么算呢?类的大小又怎么算呢?

对c语言的结构体大小计算还不清楚的可以去看看我之前的博客,专门介绍了结构体内存对齐原则

c语言结构体的内存对齐-CSDN博客

观察以下代码

7.2为什么空类的大小为1?

 分析A3,A3是一个空类,为什么sizeof A3等于1呢?

在C++中,一个空类(没有任何成员变量或成员函数)的大小通常为1字节。这是因为在C++中,空类的实例需要有独一无二的地址,以便在使用指针操作时能够区分不同的对象

7.3函数在类里面的存储形式? 

分析A2,A2类体只有一个函数,为什么sizeof A2等于1呢?

首先我们先思考这样一个事实。对于一个类来说,其每个实例化对象里的成员变量的值可能都不一样。但是其中的成员方法都是一样的。如果每实例化一个对象都开辟空间存放其成员函数,这样一来就会浪费很多空间。于是,c++将类中的成员函数都存储在程序的代码段(text segment)中,而不是存储在对象的实例中这样可以节省内存空间这意味着所有对象共享相同的成员函数代码

简单理解就是,有一个公共区域存储该类的成员函数,每当有对象要调用其成员函数时,就去这个区域里面去调用。

这也就是为什么我们siziof A2等于1了

7.4面试题

1、结构体怎么对齐?为什么要进行内存对齐?

2、如何让结构体按照指定的对齐参数进行对齐?能否按照3、4、5即任意字节对齐? 

3、什么是大小端?如何测试某台机器是大端还是小端,有没有遇到过要考虑大小端的场景

之前的博客里有讲解

c语言结构体的内存对齐-CSDN博客

c语言内功修炼--深度剖析数据的存储-CSDN博客

8.this指针

8.1this指针的引出

观察以下代码

#include<iostream>
using namespace std;

//日期类
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(2024, 3, 2);
	d1.Print();

	d2.Init(2024, 3, 1);
	d2.Print();

	return 0;
}

上述代码定义了一个日期类,类里面有Init和Print两个成员函数,函数体中没有对象的区分,当实例化对象d1调用Init函数时,该成员函数怎么区分是哪个对象来调用它的呢?因为之前我们已经讲过,类里面的成员函数都是放在外面的公共区域,代码只有一份,也就是说,如果不能区分是哪个对象来调用成员函数,那就会发生错误,毕竟每个对象的成员变量都是不一样的。

于是,c++通过引入一个this指针来解决类似问题。

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

也就是说,在你定义一个成员函数的时候,这个函数的参数里面就有一个你隐式的this指针,在你实例化某个对象并调用这个成员函数的时候,这个this指针会指向该对象的地址,告诉这个函数是哪个对象在调用它。

 8.2this指针的特性

1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值

2. 只能在“成员函数”的内部使用

3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给 this形参。所以对象中不存储this指针。

4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递

8.3关于this指针的面试题

1. this指针存在哪里?

编译器在生成程序时加入了获取对象首地址的相关代码。并把获取的首地址存放在了寄存器ECX中(VC++编译器是放在ECX中,其它编译器有可能不同)。也就是成员函数的其它参数正常都是存放在栈中。而this指针参数则是存放在寄存器中。类的静态成员函数因为没有this指针这个参数,所以类的静态成员函数也就无法调用类的非静态成员变量。

2. this指针可以为空吗? 

this指针是否可以为空需要看情况,如果被调用的成员函数本身与成员属性无关,也就意味着不需要解引用this指针,不解引用this指针的话,也就随便它是个啥了。

举例:

有的朋友可能会问,t不是nullptr吗?为什么解引用还不会报错?有->符号并不意味着就解引用了,要看是否真的访问了所指空间。而上面我们已经讲过,print函数并不在类里面,也就意味着t->print()并没有在t的地址上去访问,所以即使t为空也能访问到里面的成员函数。只不过这个时候需要注意判断this指针是否可以为空

8.4思考:

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

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

相关文章

使用pyannote-audio实现声纹分割聚类

使用pyannote-audio实现声纹分割聚类 # GitHub地址 https://github.com/MasonYyp/audio1 简单介绍 pyannote.audio是用Python编写的用于声纹分割聚类的开源工具包。在PyTorch机器学习基础上&#xff0c;不仅可以借助性能优越的预训练模型和管道实现声纹分割聚类&#xff0c;还…

图解Vivado工程的目录结构

一、目录结构 ​在使用Vivado进行工程设计时&#xff0c;创建工程以及运行工程的过程中都会生成大量的目录和文件&#xff0c;下面图将对目录和文件结构及功能进行一个简单说明。 工程示例图 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 二、参考资料…

windows下安装cnpm

cnpm是淘宝团队开发的一个针对中国用户的npm镜像源&#xff0c;它是npm的一个定制版本。由于国外的npm源在国内访问速度较慢&#xff0c;所以cnpm镜像源可以提供更快的下载速度。cnpm的使用方式与npm基本相同&#xff0c;只需将npm替换为cnpm即可。 要想使用cnpm等先安装node.…

面试准备:排序算法大汇总 C++

排序算法总结 直接插入排序 取出未排序部分的第一个元素&#xff0c;与已排序的部分从后往前比较&#xff0c;找到合适的位置。将大于它的已排序的元素向后移动&#xff0c;将该元素插入到合适的位置。 //1. 直接插入排序 void InsertionSort(vector<int>& nums){f…

如何确保JDK版本与操作系统架构匹配?

1. 序言 最近的工作中&#xff0c;需要升级JDK版本到17.0.7&#xff0c;以解决一个JDK bug&#xff1a;JDK-8299626该bug的core dump关键字如下&#xff1a;SIGSEGV in PhaseIdealLoop::build_loop_late_post_work公司JDK团队提供的、包含JDK的基础镜像&#xff0c;有aarch64和…

深入了解Java虚拟机(JVM)

Java虚拟机&#xff08;JVM&#xff09;是Java程序运行的核心组件&#xff0c;它负责解释执行Java字节码&#xff0c;并在各种平台上执行。JVM的设计使得Java具有跨平台性&#xff0c;开发人员只需编写一次代码&#xff0c;就可以在任何支持Java的系统上运行。我们刚开始学习Ja…

Launch学习

参考博客&#xff1a; (1) 史上最全的launch的解析来啦&#xff0c;木有之一欧 1 ROS工作空间简介 2 元功能包 src目录下可以包含多个功能包&#xff0c;假设需要使用机器人导航模块&#xff0c;但是这个模块中包含着地图、定位、路径规划等不同的功能包&#xff0c;它们的逻…

【Python】1. 背景知识

认识 Python 计算机基础概念 什么是计算机? 很多老一辈的人, 管下面这个叫做计算机. 然鹅, 它只是 “计算器”, 和计算机是有很大区别的. 现在我们所说的计算机, 不光能进行算术运算, 还能进行逻辑判断, 数据存储, 网络通信等等功能,。 以至于可以自动的完成非常复杂的工作…

SLAM基础知识-卡尔曼滤波

前言&#xff1a; 在SLAM系统中&#xff0c;后端优化部分有两大流派。一派是基于马尔科夫性假设的滤波器方法&#xff0c;认为当前时刻的状态只与上一时刻的状态有关。另一派是非线性优化方法&#xff0c;认为当前时刻状态应该结合之前所有时刻的状态一起考虑。 卡尔曼滤波是…

java垃圾回收

垃圾回收 一个对象如果不再使用&#xff0c;需要手动释放&#xff0c;否则就会出现内存泄漏。我们称这种释放对象的过程为垃圾回收&#xff0c;而需要程序员编写代码进行回收的方式为手动回收。 内存泄漏指的是不再使用的对象在系统中未被回收&#xff0c;内存泄漏的积累可能…

LCR 124. 推理二叉树

解题思路&#xff1a; 分治 class Solution {// 一个哈希表用于存储中序遍历中每个值对应的索引&#xff0c;用于快速查找HashMap<Integer,Integer> map new HashMap<>();// 保存前序遍历的结果数组int[] preorder;// 主函数&#xff0c;传入前序和中序遍历的结果…

Vue中的计算属性和方法有什么区别?

Vue.js是一款流行的JavaScript前端框架&#xff0c;提供了丰富的功能和便捷的开发方式。在Vue中&#xff0c;计算属性和方法是常用的两种方式来处理数据和逻辑。但它们之间存在一些区别&#xff0c;本文将详细介绍Vue中计算属性和方法的区别&#xff0c;并通过示例代码加深理解…

UE4c++ ConvertActorsToStaticMesh ConvertProceduralMeshToStaticMesh

UE4c ConvertActorsToStaticMesh 创建Edior模块&#xff08;最好是放Editor模块毕竟是编辑器代码&#xff09;创建蓝图函数UBlueprintFunctionLibraryUTestFunctionLibrary.hUTestFunctionLibrary.cpp:.Build.cs 目标:为了大量生成模型&#xff0c;我们把虚幻带有的方法迁移成函…

一周学会Django5 Python Web开发-Django5详细视图DetailView

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计28条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的停车位检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;开发停车位检测系统对于优化停车资源管理和提升用户体验至关重要。本篇博客详细介绍了如何利用深度学习构建一个停车位检测系统&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并结合了YOLOv7、YOLOv6、YOLOv5的性能对比&#xf…

python-分享篇-控制摄像头

文章目录 准备代码效果 准备 安装cv2 pip install opencv-python &#xff08;如果只用主模块&#xff0c;使用这个命令安装&#xff09; pip install opencv-contrib-python &#xff08;如果需要用主模块和contrib模块&#xff0c;使用这个命令安装&#xff09; 我的代码l里…

Vue+SpringBoot打造知识图谱构建系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 知识图谱模块2.2 知识点模块2.3 学生测评模块2.4 学生成绩模块 三、系统展示四、核心代码4.1 查询知识点4.2 新增知识点4.3 查询知识图谱4.4 查询学生成绩4.5 查询学生成绩 五、免责说明 一、摘要 1.1 项目介绍 基于J…

AJAX 学习笔记(Day3)

「写在前面」 本文为黑马程序员 AJAX 教程的学习笔记。本着自己学习、分享他人的态度&#xff0c;分享学习笔记&#xff0c;希望能对大家有所帮助。推荐先按顺序阅读往期内容&#xff1a; 1. AJAX 学习笔记&#xff08;Day1&#xff09; 目录 3 AJAX 原理 3.1 XMLHttpRequest 3…

Stable Video文本生成视频公测地址——Scaling Latent Video Diffusion Models to Large Datasets

近期&#xff0c;Stability AI发布了首个开放视频模型——"Stable Video"&#xff0c;该创新工具能够将文本和图像输入转化为生动的场景&#xff0c;将概念转换成动态影像&#xff0c;生成出电影级别的作品&#xff0c;旨在满足广泛的视频应用需求&#xff0c;包括媒…

为什么要在业务系统中引入大宽表?

在高度系统化驱动的业务中&#xff0c;查看业务报表已经是一个很常见的需求了。在分工非常明确的大型企业里&#xff0c;往往有专门的数据分析团队 BI 或者数据开发团队&#xff0c;他们能够胜任此类需求&#xff08;但也未必是轻松的&#xff0c;或者说高效的&#xff09;。 …