| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> C++类和对象(上) -> 正文阅读 |
|
[C++知识库]C++类和对象(上) |
目录 上一篇博客我向大家介绍了面向过程和面向对象的一些区别,并捎带着引入了一点点类和对象的概念,今天我们正式来看一下类和对象。 https://blog.csdn.net/SAKURAjinx/article/details/126990400 C++ struct的升级为了引入类,C++先拿C语言的struct开刀了。 首先C++的struct还是兼容C的用法,但同时也将其升级成了类。也就是说struct里面不仅可以放以前那一套(属性),还可以放入方法(函数)了。
并且因为struct升级成了类,所以stu ,teacher 是类名,结构体实参命名可以不加struct,直接用类名。
类的定义
?访问限定符?C++有封装、继承、多态,为了更好地控制封装,C++定义了访问限定符。
类域class里面的域叫类域。 之前C++命名空间域也是一个域。
问大家一个问题,类里面可以这样像命名空间一样访问吗? 不可以。因为class 里面是声明,没有空间,自然也没有age的空间,不能访问。 要访问age,如下所示:
如果是静态的,可以用上面那种方式访问,后面再讲。 类的声明和定义分离声明和定义的原因: 1、增强可读性。比如公司里需要你加入一个项目,你要迅速了解项目的基本内容,可以查看项目程序的声明及注释。? 如果声明和定义在一起,阅读、查找起来就很吃力。 2、增强代码安全性,防止源代码泄漏。 先来看一种声明和定义分离的情况:
我们发现一个问题,project.cpp里面,函数定义时,分不清哪个是stu的哪个是teacher的。 因此,此时要加上类的限定。
另外,如果在类里面定义函数,那么编译器会默认函数是内联的。 C++类的一些约定我们在类里定义变量时,通常会在前面或后面加_? 以示区分。 如:int _year;???? int year_; 还有:int? m_year;??? int mYear 具体以公司惯例为主。 封装面向对象有三大特性:封装、继承、多态。当然还有一些其他特性(如反射等),但这三个是最主要的。 我们现在所学的类就是封装的一大体现。其本质就是把一系列相关的东西都封到一个地方。 类里面有公有和私有,想给外面使用的就设为公有(如函数),不想给外面使用的就设为私有(如变量)。 以数据结构的栈为例,C语言实现的时候相对自由一些,它的数据和方法(变量和函数)不是在一起的,是分离的。 而C++则是将数据和方法都封装在了一个类下。 ?左边C语言因为相对自由,没有封装的约束,也就可以通过访问变量随意修改成员。比如访问栈顶数据,本来需要调用StackTop函数,但是因为这个函数实现就两行太过简单,很多人直接就访问成员变量,这样会出现问题(因为不知道top初始设计是-1还是0)。 C++就不存在上述问题,因为封装在一起,数据是私有的,无法从外部访问,必须调用方法(函数),这样就增加了安全性,能更好地管理。 类对象模型如何计算对象的大小 ?计算类的大小时,和之前讲的结构体内存对齐那一块一样,都涉及到内存对齐相关原则,不清楚的老铁可以看一下我的博客:自定义类型————结构体、位段、枚举类型、联合体_SAKURAjinx的博客-CSDN博客 ? ?先说结论,这里类A的大小不是8,而是1.? 很多老铁会把函数也算进大小里面,其实大佬在设计的时候没有将函数算进去,只计算对象的大小。 这里大佬在设计存储方式的时候有三种想法: ?第一种:将对象和方法都存进去。 这种显然不好,太浪费空间了。pass ?第二种:存对象及函数的地址。 毫无疑问,对象肯定都要存的,将函数放到一起,用一个指针指向它,保存这个地址就可以访问所有函数了。 ?第三种是大佬选择的方法,只存对象,将函数放到一块公共代码区,每个对象想访问就可以访问到。 方法二比方法三多存了一个地址,其实是没必要的,函数都在公共代码区了,对象都能轻易调用,没有必要特地保存一个地址取找这些函数。 既然函数不算进类的大小,那如果类里面没有对象呢?
?不论是类里面只有函数没有变量,还是什么都没有,编译器默认给的大小是1,不是0 也就是说编译器会给1个字节占位,它不存储有效数据,仅标识类存在。 因为如果需要取类的地址,连空间都没有就不行了。 ? 隐含的this指针
this指针是关键字,只能叫this,不能用that...代替。 我们用日期类来引出隐含的this指针,看上面代码,结果如下图: 上面已经讲过了,对象是去类里面找,但是函数不是去类里面找的,是去公共代码区找的,不同的对象调用的是同一个,那为什么结果会不同呢? 这就印证了this指针的存在。其实类里面有一个隐含的this指针,它指向调用函数的对象。
?d1调用,传给this指针的就是d1 的地址;?d2调用,传给this指针的就是d2 的地址。 因此,结果才会不同。 this指针是隐含的、默认的,不需要我们自己加上。在函数参数里加会报错。 虽然定义和传递都不能加this,但是我们可以用,像在函数体里面用 this->就没问题。 正因如此,在类外部不能直接用类访问里面的函数: ?因为类里的函数要传d1 \ d2的地址给this指针,但是这里没有定义d1 \ d2,只有类名,编译器不知道传什么给this,就报错了。 ? 其实this指针接收实参传过来的地址时,会加个const修饰: ?这里const修饰的是this指针本身,而非它指向的值(解引用访问)。 也就是说 this 指针是不能修改的,this = nullptr(X) ?this指针两道经典面试题一、this指针存在哪里? 两种经典错误解答:1、在常量取区(代码段) ????????????????????????????????? 2、在对象里 答案是存在栈帧中。因为this指针是形参。 二、 ?乍看之下,好像两道题是一样的,但其实有坑在里面。 很多人以为p是空指针,空指针解引用访问肯定会崩溃,所以都选了B。 这里就要结合我们上面讲的,p是空指针不假,但是注意:print函数的地址是在公共代码区的(代码段),而非在对象里,编译器去找print函数不会去对象里找,而是直接去代码段,所以这里不发生解引用。p是A的指针,直接传给print函数的this指针,指针可以为空,不会报错,因此正常运行,第一题选C。 第二题传指针之前都是一样的,当p指针传给this后,this是nullptr,还原编译器的写法就是:
空指针this解引用访问_a就会崩溃,所以第二题选B。 |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 9:42:49- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |