【C++】什么是类与对象?

news2024/11/17 4:26:56

🦄个人主页:修修修也

🎏所属专栏:C++

⚙️操作环境:Visual Studio 2022


面向对象概述

        面向对象是一种符合人类思维习惯编程思想。现实生活中存在各种形态不同的事物,这些事物之间存在着各种各样的联系。在程序中使用对象来映射现实中的事物,使用对象的关系来描述事物之间的联系,这种思想就是面向对象。
        对于学习过其他编程语言的人员来说,可能会想到面向过程。面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一一实现,使用的时候依次调用就可以了。面向对象则是把构成问题的事物按照一定规则划分为多个独立的对象,然后通过调用对象的方法来解决问题。当然,一个应用程序会包含多个对象,通过多个对象的相互配合即可实现应用程序所需的功能,这样当应用程序功能发生变动时,只需要修改个别的对象就可以了,从而使代码更容易维护。
        面向对象的特点可以概括为封装继承多态,接下来针对这三种特性进行简单介绍。

       封装

            封装是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体实现细节,这就是封装思想。例如,用户使用计算机,只需要使用手指敲键盘就可以了,无须知道计算机内部是如何工作的,即使用户可能碰巧知道计算机的工作原理,但在使用时,并不完全依赖计算机工作原理这些细节。

       继承

            继承主要描述的就是类与类之间的关系,通过继承,可以在无须重新编写原有类的情况下,对原有类的功能进行扩展。例如,有一个汽车的类,该类中描述了汽车的普通属性和功能。而轿车的类中不仅应该包含汽车的属性和功能,还应该增加轿车特有的属性和功能,这时,可以让轿车类继承汽车类,在轿车类中单独添加轿车特有的属性和功能就可以了。继承不仅增强了代码的复用性,提高了开发效率,还为程序的维护补充提供了便利。

       多态

            多态指的是在一个类中定义的属性和功能被其他类继承后,当把子类对象直接赋值给父类引用变量时,相同引用类型的变量调用同一个方法所呈现出的多种不同行为特性。例如,当听到cu这个单词时,理发师的行为表现是剪发,演员的行为表现是停止表演等。不同的对象,所表现的行为是不一样的。


类是什么?

  • 类是面向对象语言的程序设计中的概念,是面向对象编程的基础。
  • 类的实质是一种引用数据类型,类似于 byte、short、int(char)、long、float、double 等基本数据类型,不同的是它是一种复杂的数据类型。因为它的本质是数据类型,而不是数据,所以不存在于内存中不能被直接操作只有被实例化为对象时才会变得可操作
  • 类是对现实生活中一类具有共同特征的事物的抽象。如果一个程序里提供的数据类型与应用中的概念有直接的对应,这个程序就会更容易理解,也更容易修改。一组经过很好选择的用户定义的类会使程序更简洁。此外,它还能使各种形式的代码分析更容易进行。特别地,它还会使编译器有可能检查对象的非法使用。
  • 类的内部封装了属性和方法,用于操作自身的成员。类是对某种对象的定义,具有行为(behavior),它描述一个对象能够做什么以及做的方法(method),它们是可以对这个对象进行操作的程序和过程。它包含有关对象行为方式的信息,包括它的名称属性、方法事件
  • 类的构成包括成员属性成员方法数据成员成员函数)。数据成员对应类的属性,类的数据成员也是一种数据类型,并不需要分配内存。成员函数则用于操作类的各项属性,是一个类具有的特有的操作,比如“学生”可以“上课”,而“水果”则不能。类和外界发生交互的操作称为接口。

C++中类的引入

        C语言结构体中只能定义变量,比如:之前在数据结构中,我们用C语言方式实现的栈,结构体中只能定义成员变量:

【数据结构】C语言实现顺序栈(附完整运行代码)

//C语言中定义顺序栈的结构体

struct Stack
{
    int *arr;
    int top;
    int capacity;
};

        并且,在C语言中,我们创建的结构体变量,只能访问自己的成员变量:

        而在C++中,结构体内不仅可以定义成员变量,也可以定义函数。现在我们以C++方式实现栈,可以发现struct中也可以定义函数:

struct Stack
{
    void Init(size_t capacity)
    {
        _arr = (int*)malloc(sizeof(int) * capacity);
        if (nullptr == _arr)
        {
            perror("malloc申请空间失败");
            return;
        }
        _capacity = capacity;
        top = 0;
    }

    //成员变量的位置可以是类内的任意地方
    int *arr;
    int top;
    int capacity;
};

        并且,在C++中,我们创建的结构体变量,是可以访问结构体成员函数的:


C++中类的定义

        虽然C++因为兼容C语言的缘故,将C语言中的struct升级为了类,但实际应用中,C++更喜欢使用class关键字来声明类。class 声明类时格式如下:

class class_name
{
    //类体:由成员函数和成员变量组成
};  

        class为定义类的关键字,class_name类的名字,{}中为类的主体,注意类定义结束后最后的分号不能省略

        类中的内容称为类的成员:类中的变量称为类的属性成员变量,类中的函数称为类的方法或者成员函数.

类的两种定义方式:

1.声明和定义全部放在类体中

需要注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。

class Stack
{
public:

    void Init(size_t capacity)
    {
        _arr = (int*)malloc(sizeof(int) * capacity);
        if (nullptr == _arr)
        {
            perror("malloc申请空间失败");
            return;
        }
        _capacity = capacity;
        _top = 0;
    }

public:

    //成员变量的位置可以是类内的任意地方
    int* _arr;
    int _top;
    int _capacity;
};

注意:为了防止在类中定义函数时像下面这样容易使成员变量函数参数混淆:

一般当声明和定义全部放在类体中时我们会将类中的成员变量名前面加_以示区分:

2.类声明与成员函数定义分别放在不同的工程文件中:

类声明放在.h文件中:

成员函数定义放在.cpp文件中,注意:成员函数名前需要加  类名::


类的访问限定符

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

访问限定符的特性:

  • public修饰的成员在类外可以直接被访问
  • protectedprivate修饰的成员在类外不能直接被访问(此处protectedprivate是类似的)。
  • 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
  • 如果后面没有访问限定符,作用域就到 } 即类结束。
  • class默认访问权限为privatestruct为public(因为struct要兼容C)。

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

C++中struct和class的区别是什么?
        C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类默认访问权限是private。在继承和模板参数列表位置,struct和class也有部分区别。


类的封装

        我们在文章一开始就介绍了面对对象的三大特性:封装,继承,多态

        封装是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体实现细节,这就是封装思想。

        封装本质上是一种管理让用户更方便使用类。比如:对于电脑这样一个复杂的设备,提供给用户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互,完成日常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件。对于计算机使用者而言,不用关心内部核心部件,比如主板上线路是如何布局的,CPU内部是如何设计的等,用户只需要知道,怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可。
        在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节控制哪些方法可以在类外部直接被使用

        在C语言中,由于对结构体没有封装的概念,从而会导致使用者通过变量对结构体中的成员变量进行任意不合规的操作。

        如下,在栈程序中,使用者就没有通过取栈顶元素函数获取栈顶元素,而通过直接访问成员变量的方式访问了栈顶元素:

        而在C++中,我们可以通过访问权限来隐藏对象内部实现细节控制哪些方法可以在类外部直接被使用,而哪些方法在类外部不可以被使用。


类的作用域

        类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员(包括变量和函数)时,需要使用 :: 作用域操作符指明成员属于哪个类域。

        如,上文中在C++中类的定义方式中我们提到的:

        有关类的作用域,有以下几点需要注意:

  • 局部域,全局域,命名空间域,类域,不同的域中可以定义同名变量。
  • 类中的变量查找优先级:局部域>类域>全局域/命名空间域(非指定展开则不查找)。
  • 局部域和全局域会影响生命周期,类域和命名空间域不会影响生命周期。

类的实例化

            用类类型创建对象的过程,称为类的实例化

  1. 类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类但并没有分配实际的内存空间来存储它;比如:入学时发放的学生信息表,表格就可以看成是一个类,来描述具体学生信息。但在还没有学生填表时,这个表格就并没有实际存储学生的任何信息。
  2. 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量。         打个比方来说,上面这个例子中的Date就类似于一个房屋建造的图纸,它规定了这个房屋建造多高,多宽,多长,以及各个地方的设计细节。但你如果不真正的将房子按照图纸建造出来,你就永远无法将家具之类的东西搬进房子里住,上图中使用Date类直接存储_year的数据就类似于要将现实世界的床搬进房屋设计图纸里住人。

类对象模型

如何计算类对象的大小

        在C语言中,我们学习过如何使用sizeof操作符计算结构体的大小,以及如何通过结构体对齐规则去计算结构体的大小(还不太了解的朋友可以移步这篇博客):

【C语言】结构体的大小是如何计算的?(结构体对齐)icon-default.png?t=N7T8https://blog.csdn.net/weixin_72357342/article/details/131135555?spm=1001.2014.3001.5502

        在C++中,对类的大小计算我们同样是使用sizeof操作符,如下例子,我们使用sizeof操作符分别计算Date类和Date类对象Birthday的大小:

class Date
{
public:
    void InitDate(int year, int mouth, int day)
    {
        _year = year;
        _mouth = mouth;
        _day = day;
    }
public:
    int _year;
    int _mouth;
    int _day;
};

int main() {
    Date Birthday;
    Birthday._year = 2000;

    int sz1 = sizeof(Date);
    int sz2 = sizeof(Birthday);

    printf("%d %d\n", sz1, sz2);
    return 0;
}

        运行查看结果,可以看到,类的大小和类对象的大小是一致的,这和结构体与结构体变量的大小计算结果一致:


类对象存储方式

        在知道了如何使用sizeof操作符计算类的大小后,我们还需要探究一下类对象究竟在内存中是怎样存储的。

        在C语言中,结构体的大小是由成员变量构成的,这我们很好理解,但在C++中,类的大小计算起来却看起来复杂的多,因为类中不仅包含了成员变量,还包含了成员函数,它们是如何存储在内存中的?它们和成员变量的关系又是怎样的?下面我们一起来探究一下:

`        如下,我们分别构建了一个类对象Date1,以及一个结构体对象Date2,分别计算他们的大小以及由它们创建的变量Birthday1,Birthday2的大小:

class Date1{
public:
    void InitDate(int year, int mouth, int day){
        _year = year;
        _mouth = mouth;
        _day = day;
    }
public:
    int _year;
    int _mouth;
    int _day;
};

struct Date2{
    int year;
    int mouth;
    int day;
};

int main() {
    Date1 Birthday1;
    Birthday1._year = 2000;

    int sz1 = sizeof(Date1);
    int sz2 = sizeof(Birthday1);
    printf("%d %d\n", sz1, sz2);

    Date2 Birthday2;
    Birthday2.year = 2000;

    int sz3 = sizeof(Date2);
    int sz4 = sizeof(Birthday2);
    printf("%d %d\n", sz3, sz4);
    return 0;
}

运行程序,我们可以发现,它们的大小是一样大的:

        也就是说,类的大小是不包含成员函数的大小的,它的大小只取决于类中的成员变量.同样的,类对象的大小也仅取决于成员变量的大小.

        这样的存储策略其实并不难理解,打个比方说,如果我们将类比作一个小区,那么类对象中的成员变量就类似于一间一间的居民楼,供用户存放个人的物品使用,而类中的成员函数则类似于小区中的凉亭或健身器材区域,它是可以提供给所有小区中的人使用的,并且所有人使用它都是一样的,因此完全不需要给每家都修一个,而是可以整个小区只修建一个,大家一起使用就可以了。

        因此,我们可以推断出,类成员的存储方式应该类似于下图这种结构:

        下面我们设计几个类来验证一下我们的推断:

//类中既有成员变量也有成员函数
class Date1 {
public:
    void InitDate(int year, int mouth, int day) {
        _year = year;
    }
public:
    int _year;
    int _mouth;
    int _day;
};

//类中只有成员函数
class Date2 {
public:
    void InitDate(int year, int mouth, int day) {
        year=2000;
    }
};

//类中只有成员变量
class Date3 {
public:
    int _year;
    int _mouth;
    int _day;
};

//类中什么都没有
class Date4 {

};

int main() {
    int sz1 = sizeof(Date1);
    int sz2 = sizeof(Date2);
    int sz3 = sizeof(Date3);
    int sz4 = sizeof(Date4);
    printf("%d %d %d %d\n", sz1, sz2,sz3,sz4);
    return 0;
}

        运行程序,得到结果:

        可以看到,类中既有成员函数也有成员变量和类中只有成员变量的大小是一样的,而类中只有成员函数和类中什么都没有的大小是一样的.

        需要注意的是,在没有成员变量的情况下,类的大小是1,它需要1字节的空间占位,表示对象存在,但不存储任何有效数据。

        需要注意的是,类中的成员变量的计算规则和C语言中的结构体一样,都遵循结构体对齐规则,所以下面这种情况中,Date1类的大小是8而不是5:

        对于结构体对齐规则的详解,感兴趣的朋友可以移步下面这篇博客:

【C语言】结构体的大小是如何计算的?(结构体对齐)icon-default.png?t=N7T8https://blog.csdn.net/weixin_72357342/article/details/131135555?spm=1001.2014.3001.5502


结语

希望这篇关于类与对象的基础博客能对大家有所帮助,欢迎大佬们留言或私信与我交流.

学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!

相关文章推荐

【C++】缺省参数(默认参数)

【C++】“Hello World!“

【C++】命名空间


慎在此祝愿全世界伟大的劳动妇女们,节日快乐!

广阔天地,大有作为!

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

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

相关文章

基于SpringBoot+Vue+ElementUI+Mybatis前后端分离管理系统超详细教程(四)——前后端数据交互

经过前面几个章节的学习我们掌握了: 1、如何使用Vue快速搭建前端工程化项目,并结合elementUI优化了界面; 基于SpringBootVueElementUIMybatis前后端分离管理系统超详细教程(一) 基于SpringBootVueElementUIMybatis前后…

软件测试入门

文章目录 一、入门1. 软件2. 软件基本组成3. 软件产生过程4. 软件测试5. 软件测试目的🏆 小结 二、测试主流技能1. 功能测试2. 自动化测试3. 接口测试4. 性能测试🏆 小结 三、测试分类1. 按测试阶段划分2. 按代码可见度划分🏆 小结 三、质量模…

信息系统项目管理师003:信息化(1信息化发展—1.1信息与信息化—1.1.3 信息化)

文章目录 1.1.3 信息化1.信息化内涵2.信息化体系3.信息化趋势 要点总结 1.1.3 信息化 信息化是一个过程,与工业化、现代化一样,是一个动态变化的过程。信息化是指培养、发展以计算机为主的智能化工具为代表的新生产力,并使之造福于社会的历史…

通过sqoop把hive数据到mysql,脚本提示成功,mysql对应的表中没有数

1、脚本执行日志显示脚本执行成功,读写数量不为0 2、手动往Mysql对应表中写入数据十几秒后被自动删除了 问题原因: 建表时引擎用错了,如下图所示 正常情况下应该用InnoDB

7-4 哲哲打游戏(Python)

哲哲是一位硬核游戏玩家。最近一款名叫《达诺达诺》的新游戏刚刚上市,哲哲自然要快速攻略游戏,守护硬核游戏玩家的一切! 为简化模型,我们不妨假设游戏有 N 个剧情点,通过游戏里不同的操作或选择可以从某个剧情点去往另…

偶极子和环形天线的辐射机理仿真分析

目录 0 引言 1 偶极子天线的辐射因素分析 1.1 偶极子天线模型设计 1.2 谐振点的出现规律 1.3 天线尺寸对辐射的影响 1.4 天线角度对辐射的影响

浅显易懂:WinForms、WPF和Electron的区别和优缺点

在开发桌面应用的时候,WinForms、WPF和Electron是绕不过去的三个技术栈,本文就详细据介绍了三者的区别和优缺点,帮助老铁们做个抉择。 一、winform wpf Electron 三者区别 WinForms、WPF和Electron是三种不同的框架和技术,用于开…

计算机中丢失缺少mfc100.dll文件该如何解决?

当你打开某个应用程序时,有时候会遇到一个“mfc100.dll丢失”或找不到mfc100.dll的错误信息提示。这种情况表明你的计算机缺少一个名为mfc100.dll的动态链接库文件。这个文件是由Microsoft VC 2010 Redistributable Package提供的,它是一组可重用的组件&…

【校园导航小程序】2.0版本 静态/云开发项目 升级日志

演示视频 【校园导航小程序】2.0版本 静态/云开发项目 演示 首页 重做了首页,界面更加高效和美观 校园指南页 新增了 “校园指南” 功能,可以搜索和浏览校园生活指南 地图页 ①弃用路线规划插件,改用SDK开发包。可以无阻通过审核并发布…

Linux的top命令解析

Top命令是什么 TOP命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况。 TOP是一个动态显示过程,即可以通过用户按键来不断刷新当前状态.如果在前台执行该命令,它将独占前台,直到用户终止该程序为止.比较准确的说,top命令提供了实时的对系…

qml中toolbox控件、ComboBox控件、PlainText实现及美化

一. 内容简介 qml中toolbox控件、ComboBox控件、PlainText实现及美化 二. 软件环境 2.1vsCode 2.2Anaconda version: conda 22.9.0 2.3pytorch 安装pytorch(http://t.csdnimg.cn/GVP23) 2.4QT 5.14.1 新版QT6.4,,6.5在线安装经常失败,而5.9版本…

相对于 Linux,Windows Server 存在的意义是什么?

相对于 Linux,Windows Server 存在的意义是什么? 在开始前我有一些资料,是我根据网友给的问题精心整理了一份「Linux 的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给…

写作文的ai的软件有吗?分享4款热门的软件!

随着科技的飞速发展,人工智能(AI)已经渗透到我们生活的方方面面,包括写作领域。许多AI工具如今能够帮助我们快速、高效地创作文章,无论是新闻稿、广告文案还是博客文章,它们都能提供有力的支持。今天&#…

linux安装todesk

xunilToDesk远程桌面软件-免费安全流畅的远程连接电脑手机ToDesk远程控制软件是一款稳定流畅的远程控制电脑手机连接软件,可远程桌面办公,远程协助运维.采用端对端加密,让每一次远程访问都安全可靠。https://www.todesk.com/linux.htmlToDesk远程控制软件是一款稳定流畅的远程控…

20.网络游戏逆向分析与漏洞攻防-网络通信数据包分析工具-数据分析工具数据类型编辑功能的实现

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 内容参考于: 易道云信息技术研究院VIP课 上一个内容:19.数据分析工具数据类型配置功能的实现 码云地址(master 分支&#…

Androidstudio实现登录按钮按下变色

在activity_main.xml中&#xff0c;写如下代码&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"androi…

华为---MSTP(一)---MSTP生成树协议

目录 1. MSTP技术产生背景 2. STP/RSTP的缺陷 ​编辑 2.1 无法均衡流量负载 2.2 数据使用次优路径 3. MSTP生成树协议 3.1 MSTP相关概念 3.2 MSTP树生成的形成过程 4. MSTP报文 1. MSTP技术产生背景 RSTP在STP基础上进行了改进&#xff0c;实现了网络拓扑快速收敛。但…

[Buuctf] [MRCTF2020]Transform

1.查壳 64位exe文件&#xff0c;没有壳 2.用64位IDA打开 找到主函数&#xff0c;F5查看伪代码 从后往前看&#xff0c;有一个判断语句&#xff0c;是两个数组进行比较的&#xff0c;我们双击byte_40F0E0查看里面的内容 所以能够推出byte_414040的内容&#xff0c;byte_4140…

【常见集合】Java 常见集合重点解析

Java 常见集合重点解析 1. 什么是算法时间复杂度&#xff1f; 时间复杂度表示了算法的 执行时间 和 数据规模 之间的增长关系&#xff1b; 什么是算法的空间复杂度&#xff1f; 表示了算法占用的额外 存储空间 与 数据规模 之间的增长关系&#xff1b; 常见的复杂度&#x…

守护Web安全:了解Web攻击与防护策略

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…