深入学习默认成员函数——c++指南

前言类和对象是面向对象语言的重要概念。 c++身为一门既面向过程,又面向对象的语言。 想要学习c++, 首先同样要先了解类和对象。 本节就类和对象的几种构造函数相关内容进行深入的解析。

目录

类和对象的基本概念

封装

类域和类体

访问限定符

private

public

protect

默认访问限定

成员函数与this指针

构造函数

初始化规则 

三个必须初始化的变量类型

默认构造函数

默认成员函数

默认构造函数

默认拷贝构造函数

拷贝构造

默认拷贝构造

析构函数

析构函数

默认析构函数


类和对象的基本概念

是一种抽象的数据类型。它规定了某种事物的特征(成员变量,可以理解为一种属性,是静态的)和行为(成员函数,可以理解为动作,是动态的)。和c语言结构体类似, 类可以看作这种事物的模板或者蓝图

对象则是类的具体实例,是具体的。拥有着类规定的特征和行为。 我们都知道, 一个蓝图可以创造许多建筑。 那么一个类也可以创建多个对象。并且每个对象都有着类似的特征和行为。 

如图就是定义的一个类,这个类规定了事物stu有三个特征:姓名, 学号, 成绩。 有着一个行为:修改成绩。并且将其实例化出对象p1, 此时p1有着这个类规定的三个特征,一个行为—— p1有着自己的名字, 有着自己的学号, 有着自己的成绩。 同时他还能修改自己的成绩。

c++的小语法相对于c语言多了许多,虽然使用方便,但是刚开始学c++也可能很难全部掌握,所以建议刚开始学习c++的时候建议勤看看小的知识点。比如c向c++过渡的一些知识点。这样学着会舒服很多, 不会有一种模糊的感觉。比如图中的成员函数的知识点就是缺省参数,这同样是c向c++过渡的一些小知识点。 但是掌握不熟悉就会迷惑。不要不信,比如我问你半缺省(int x = 10, int y )这样是否正确,你根据你心里的答案, 然后拟定传参(1), 你看看是否正确?这个1是给谁?如果你很懵, 那你可以在看完这篇文章后去复习它。恭喜你对这个知识点又加深了一点理解。 

封装

类和对象三大特征:封装, 继承和多态,这里讲解封装, 继承和多态后续再说。

首先, 封装的概念很好理解, 就是一个或多个特征属性一个或多个行为方法封装起来。只对外公布接口。使用人通过接口操作修改对象的属性。 封装有利于数据的安全性完整性同时有利于代码的模块化可维护

图中的student类封装起来了三个特征变量:name, num, grade。 一个接口函数revise_grade

图中private, public是访问限定符, 决定了类的实例是否可以直接调用类的成员。

类域和类体

类域类体是类和对象的两个重要组成部分。

类域是指类的属性和特性, 也就是类的成员变量。 类域可以是公共的(public),私有的(private)或受保护的(protected)。公共的类域可以被类的外部访问私有的类域只能在类内部本地访问。受保护的类域这里不解释, 可以看作和私有的类域相同。

类体是指包含在类声明中的代码块,它定义了类的行为和功能。类体包含了构造函数、成员函数、成员变量,以及其他相关代码。也就是说类体包含类域

访问限定符

访问限定符有三个: private, public, protect.

private

private的意思的私有, 在private以下定义的成员不能被类的实例直接访问到。 只能通过成员函数间接访问。 

这里可以利用成员函数revise_grade间接访问

public

public的意思是公有, public之后定义的成员可以被类的实例访问。

 

protect

protect和private类似, 在他们之后定义的成员都不可直接访问。

默认访问限定

访问限定符的范围是该访问限定符到下一个访问限定符的中间的内容。如果下面没有访问限定符, 那么就是之后的所有范围。

 struct的默认访问限定是public;

class的默认访问限定是private。

这些记住就行。

成员函数与this指针

要理解封装的概念, 还要理解this指针在类中起到的作用。

类中的成员函数默认第一个形参都是this指针, this指针是一个关键词,并且这个this指针调用该函数的对象。我们平常定义构造函数或者成员函数是看不到定义this指针知识将this指针隐藏了。

this指针可以让我们找到特定的对象

构造函数

构造函数是类和对象中新添的一种概念。类在进行实例化时会自动调用自己的构造函数。

如图红框框就是定义的一个构造函数,构造函数的定义实现方式与普通函数有两处不同:

1.构造函数没有返回值

2.构造函数有符号化列表,也就是图中的绿框框。

符号化列表的初始化使用括号的方式括号中是初始化的数值。这里三个变量分别是_name, _num, _grade, 然后通过形参name, num, grade对他们进行赋值。

初始化规则 

下面请仔细阅读。很复杂,很重要。

首先, 构造函数的执行方式顺序先初始化列表再函数体。

然后,初始化列表的执行顺序不是从上到下, 而是按照成员变量的声明顺序进行初始化。

初始化列表中没有初始化的对象, 比如_name, 就只能等到函数体再初始化。

初始化列表对内置类型就是如图中的初始化方式注意, 是内置类型才是上面的方式。自定义类型就没有这么简单了。

首先构造函数的执行顺序不会改变。 但是如果成员变量中有自定义类型的话, 它在初始化的时候, 会去调用自己相应的构造函数。 (因为对内置类型编译器可以直接进行赋值拷贝工作。但是对于自定义类型, 编译器无法自己进行复制拷贝工作。 所以只能去调用类型本身的构造函数。 这其实就是套娃的过程:如果调用的构造函数中还有自定义类型的初始化, 那么就要再去调用那个自定义类型的构造函数,直到调用的构造函数中没有自定义类型 

-------------------------------------------------------------------------------------------------------------------------

以上, 是将自定义类型显示在符号化列表初始化的情况。 如果没有在符号化列表初始化的话。 那么编译器会自动对该自定义类型变量进行初始化。并且初始化时不传参,就是这个意思

就相当于这里的_b进行初始化的时候没有传参。

以上, 就是初始化列表对于自定义类型以及内置类型初始化的规则。 

现在引入两个概念, 一个概念是:三种必须在初始化列表初始化的变量类型。 

第二个概念是默认构造函数的概念。 

三个必须初始化的变量类型

三个必须在初始化列表初始化的变量类型:引用类型const修饰的常变量, 以及上面讲的自定义类型。 

那么为什么会有这样的规定?

首先引用类型必须在定义的时候初始化类的实例化的同时也是对类的特征,属性进行初始化的时候。如果这一次没有初始化。 那么之后再对类的特征进行处理, 那不是初始化。 那叫赋值。 

所以必须对引用类型进行初始化。 

至于const修饰的常变量同样的道理, 因为必须在定义的时候初始化, 那么就必须在初始化列表初始化。 你可能有疑惑说为什么必须在初始化列表, 在构造函数的函数体初始化不行吗?其实, c++中规定了, 初始化列表的叫初始化, 函数体中的是赋值。 

-----------------------------------------------自定义类型很重要--------------------------------------------------

自定义类型为什么规定不做解释, 只需要知道这样规定就好。重点是自定义类型与上面两个有点差异。 虽然自定义类型也必须初始化。 但是如果我们不对它进行初始化, 编译器不会报错。 而是自己去调用自定义类型的默认构造函数。 这就叫自定义类型的隐式初始化

-------------------------------------------------------------------------------------------------------------------------

默认构造函数

那么什么是默认构造函数, 这就是我们的第二个要引入的概念:

默认构造函数就是:没有形参, 或者形参全缺省的构造函数。 

默认成员函数

在c++的类的成员函数中,有六个特殊的成员函数, 被称为默认成员函数

默认成员函数的意思就是如果不定义他们, 系统就会自动生成。

这里主要分析三个:默认构造函数

                                默认拷贝构造函数

                                析构函数

默认构造函数

首先, 什么是默认构造函数,这个概念在上面我们刚刚提到。 这里不做赘述。

那么编译器生成的默认构造函数什么样的?如图:

如图中红框框,编译器就会默认生程这样的默认构造函数。

由此我们可以知道。 这里生成的默认构造函数虽然是个空函数体, 空初始化列表。 但是通过上面的知识我们直到。 他会对自定义类型进行处理——自定义类型的隐式初始化。 

所以:默认构造函数的作用是对内置类型不做任何处理。 但是对于自定义类型会去调用它的默认构造函数

如果我们定义了任意一个构造函数, 编译器都不会生成默认构造函数。 

这个时候我们如果这样定义, 就会报错, 因为没有可以调用的构造函数。 

 但是我们如果不定义这个构造函数, 就可以编译通过, 因为此时编译器默认生成了一个空的默认构造函数, 不需要传参。 可以匹配p1

 有一个好办法就是定义全缺省的默认构造函数, 这样就可以一劳永逸, 不必担心传参是否有匹配的构造函数的问题:

默认拷贝构造函数

在学习默认拷贝构造函数之前我们要先学习拷贝构造函数

拷贝构造

拷贝构造是构造函数的一种重载形式。 它的参数是类本身实例化对象。意思就是将已经实例化的对象的值拷贝给将要实例化的对象。

 当我们使用对象初始化对象的时候就会调用拷贝构造。

默认拷贝构造

默认拷贝构造只对内置类型进行浅拷贝操作。如果是涉及到动态分配问题。那么就达不到我们的要求。 因为编译器不会对动态内存分配的内存里的数据进行拷贝。

像图中, 只是p1的_name成员保存的地址赋值给了p2的_name成员。

但是, 这不符合我们的要求。 所以我们就不能使用默认拷贝构造函数。 而是需要我们自己定义拷贝构造函数。 

像如图中自己定义的拷贝构造就是深拷贝。  

析构函数

拷贝构造一样, 在学习默认析构函数之前我们应该了解以下析构函数。

析构函数

析构函数就是对空间进行释放。 对于内置类型来说, 不需要定义析构函数, 因为编译器会自动对内置类型进行释放。 但是涉及到资源分配的问题。 编译器无法直接对资源分配空间进行释放。 所以就用到了析构函数。

析构函数的函数名称是类名前面加上~, 并且析构函数不接受任何传参。 同时析构函数最多只能有一个。

默认析构函数

编译器默认生成的析构函数就是默认构造函数。 默认构造函数的类体是空。对于内置类型不做处理, 对于自定义类型会去调用该自定义类型的构造函数。 

如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数即可;但是有资源申请时,否则会造成资源泄漏。

如何区分改写不该写呢?其实, 只要你自己定义了拷贝构造函数的时候, 就要自己手动定义析构函数。 因为只要你自己的定义了拷贝构造, 说明就涉及到了深拷贝问题。 深拷贝就是内存资源分配的问题。 就要定义析构。

以上就是本节的全部内容。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【基于langchain + streamlit 完整的与文档对话RAG】

本地部署文档问答webdemo 支持 pdf支持 txt支持 doc/docx支持 源文档索引 你的点赞和收藏是我持续分享优质内容的动力哦~ 废话不多说直接看效果 准备 首先创建一个新环境(选择性) conda create -n chatwithdocs python3.11 conda activate chatwith…

数据库规范化设计案例解析

1.介绍 数据库规范化设计是数据库设计的一种重要方法,旨在减少数据库中的冗余数据,提高数据的一致性,确保数据依赖合理,从而提高数据库的结构清晰度和维护效率。规范化设计通过应用一系列的规范化规则(或称“范式”&a…

springboot的Converter和HttpMessageConveter

Converter和HttpMessageConveter是springboot和springmvc在处理请求的时候需要用到的。但是这两者的完全是不一样的,作用的地方也不一样。 1,springboot和springmvc处理请求的流程 先来回顾一下处理请求的流程: 用户向服务器发送请求&#…

【C++精简版回顾】22.流迭代器(输入输出迭代器)

1.输出迭代器 1.节点&#xff0c;重载 struct student {string name;int age; }; ostream& operator<<(ostream& out,student stu) {out << stu.age << stu.name ;return out; } 2.main int main() {//输入流迭代器int array[6] { 1,2,3,4,5,6 };os…

Python批量提取Word文档表格数据

在大数据处理与信息抽取领域中&#xff0c;Word文档是各类机构和个人普遍采用的一种信息存储格式&#xff0c;其中包含了大量的结构化和半结构化数据&#xff0c;如各类报告、调查问卷结果、项目计划等。这些文档中的表格往往承载了关键的数据信息&#xff0c;如统计数据、项目…

2021年中国环境统计年鉴、工业企业污染排放数据库

《中国环境统计年鉴》是国家统计局和生态环境部及其他有关部委共同编辑完成的一本反映我国环境各领域基本情况的年度综合统计资料。收录了上一年年全国各省、自治区、直辖市环境各领域的基本数据和主要年份的全国主要环境统计数据。 内容共分为十二个部分,即:1.自然状况;2.水环…

性能测试总结 —— 工具选型篇!

本篇文章主要简单总结下性能测试工具的原理以及如何选型。性能测试和功能测试不同&#xff0c;性能测试的执行是基本功能的重复和并发&#xff0c;需要模拟多用户&#xff0c;在性能测试执行时需要监控指标参数&#xff0c;同时性能测试的结果不是那么显而易见&#xff0c;需要…

Java详解:单列 | 双列集合 | Collections类

○ 前言&#xff1a; 在开发实践中&#xff0c;我们需要一些能够动态增长长度的容器来保存我们的数据&#xff0c;java中为了解决数据存储单一的情况&#xff0c;java中就提供了不同结构的集合类&#xff0c;可以让我们根据不同的场景进行数据存储的选择&#xff0c;如Java中提…

chrome高内存占用问题

chrome号称内存杀手不是盖的&#xff0c;不设设置的话&#xff0c;经常被它内存耗尽死机是常事。以下自用方法 1 自带的memory saver chrome://settings/performance PerformanceMemory Saver When on, Chromium frees up memory from inactive tabs. This gives active tab…

删除数据表

oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 删除数据表属于数据库对象的操作 drop table 表名称; 删除 emp30 表 SQL> drop table emp30;表已删除。 上面这个语句运行后&#xff0c;就会把数据表 emp30 删除 在…

考虑局部遮阴的光伏PSO-MPPT控制MATLAB仿真

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 简介 光伏电池阵列的输出特性曲线不是线性变化的。当光伏电池遮荫时&#xff0c;产生的功 率会不断变化&#xff0c;致使光伏电池阵列的输出功率不断变化&#xff0c;其输出特性曲线呈现多峰值的现象。 多峰…

游戏免费下载平台模板源码

功能介绍 此游戏网站模板源码是专门为游戏下载站而设计的&#xff0c;旨在为网站开发者提供一个高效、易于维护和扩展的解决方案。 特点&#xff1a; 响应式设计&#xff1a;我们的模板可以自适应不同设备屏幕大小&#xff0c;从而为不同平台的用户提供最佳的浏览体验。 …

Python之Web开发初学者教程—ubuntu中配置python3

Python之Web开发初学者教程—ubuntu中配置python3 ubuntu 默认安装了python 3.6.9 安装后默认不识别python命令&#xff0c;需要在bin下创建创建链接 ln -s /usr/bin/python3.6 /usr/bin/python 同理&#xff1a;pip3 符号链接为pip ln -s /usr/bin/pip3 /usr/bin/pip 安装p…

Linux命令-使用操作

Linux命令-使用操作 目录 Linux命令-使用操作软件安装yum systemctl软链接时间IP地址、主机名域名解析虚拟机配置固定IP网络传输下载和网络请求端口端口类型端口查看 进程管理主机状态系统资源监控磁盘使用信息CPU、磁盘相关信息网络状态监控 环境变量上传下载压缩解压压缩格式…

网络通信另个角度的认识(进程间通信),端口号(为什么要有,和pid的关系,分类,如何封装,和进程的定位原理+对应关系),客户端如何拿到服务端的port

目录 另一个角度认识网络通信 端口号 引入 -- 为什么要有端口号 问题 解决 端口号和pid 举例 介绍 分类 知名端口 注册端口 动态端口 客户端如何知道服务端的端口号 封装端口号 定位原理 进程和端口号的对应关系 数据如何被上层进程读到 另一个角度认识网络…

docker + nginx打包前端镜像

项目场景&#xff1a; 前端使用angular开发&#xff0c;Dockerfile如下&#xff1a; FROM nginx:1.16.1 AS base WORKDIR /app COPY nginx.conf.template /etc/nginx/ CMD ["/bin/bash", "-c", "envsubst ${APP_VERSION} < /app/index.html > …

镜面不锈钢氮气柜主要功能和应用领域介绍

镜面不锈钢氮气柜是一种专为特殊物品储存设计的高级储存设备&#xff0c;它结合了不锈钢材质的优良耐腐蚀性、易清洁性和氮气储存技术&#xff0c;确保内部储存的物品处于高度洁净、干燥且稳定的低氧环境中。以下是其主要功能介绍&#xff1a; 防潮保护&#xff1a;氮气柜通过填…

Cloudflare Tunnel:无惧DDOS_随时随地安全访问局域网Web应用

利用此方法&#xff0c;您可以在局域网&#xff08;尤其是NAS&#xff09;上搭建的Web应用支持公网访问&#xff0c;成本低而且操作简单&#xff01; 如果这是博客的话&#xff0c;它还可以有效防止DDOS攻击&#xff01; 准备工作&#xff1a; 需要一个域名&#xff08;推荐N…

安泰ATA-5420前置微小信号放大器有什么用

前置微小信号放大器&#xff08;也称为前置放大器&#xff09;是一种电子设备&#xff0c;主要用于放大微弱的输入信号&#xff0c;以便更好地进行后续信号处理和分析。它在各种领域中发挥着重要作用&#xff0c;包括科学研究、医学诊断、通信系统等。 前置微小信号放大器在科学…

在web中应用mybatis

搭建环境 数据库表的设计 create table bank(id bigint auto_increment primary key ,actno varchar(255) comment "账号",balance decimal(15,2) comment "余额" ); insert into bank values(1,act001,50000); insert into bank values(2,act002,0);添加…