c++初阶——类和对象(下)

news2025/1/16 21:44:25

大家好,我是小锋,今天我们来学习我们类和对象的最后一个章节,我们本期的内容主要是类和对象的一些细节进行讲解

再谈构造函数

我们在初始化时有两种方式一种是函数体内初始化,一种是初始化列表

我们先来看看日期类的初始化

构造函数体中的语句只能将其称作为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。

初始化列表

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。

简单来说初始化列表是每个成员定义的地方,这个时候大家要问了,这个初始化列表有什么用?

那让我们来看看

1,const 成员变量

我们正常写在函数体中是不是就行不通过了,这是因为const 成员变量在定义时就必须初始化

我们用初始化列表就可以了

2,引用的成员变量

还是使用初始化列表就可解决

3,自定义类型成员初始化 (该类没有默认构造函数)

注意: 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)

接下来我们来看看初始化列表的一些细节

我们来从代码中来分析

我们对上面的代码进行调试我们可以发现在初始化列表,我们并没有写_day的定义,编译器会自动定义并且赋随机值,

其实,初始化列表是成员变量定义的地方,而我们在类中写的成员变量是在声明,不管我们写不写初始化列表,成员变量都会先在初始化列表先定义,内置类型就赋随机值,自定义类型就调用默认的构造函数,进行赋值。

当我们给了显示值,在初始化是就用显示值初始化,没有就用缺省值初始化。

初始化列表初始化的顺序是,变量声明的顺序。

总结

1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)

2. 类中包含以下成员,必须放在初始化列表位置进行初始化:

引用成员变量

const成员变量

自定义类型成员(该类没有默认构造函数)

3. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。

4. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关

explicit关键字

我们先来看下面的一段代码

可能有些同学会不信我们可以来验证一下(因为编译器优化,所以要想看见过程可以使用比较老的编译器),我们这里从另一个角度去分析

如果我们不想发生隐式类型转换,可以用explicit关键字去修饰构造函数

像这样

这样就禁用了隐式类型转换

在c++11中加入了多参数的隐式类型转换

static成员

引出

问大家一个问题,我们怎么知道我们构造了多少个对象,又怎么知道有多少个对象正在被使用

对于这个问题我们很自然的想到一个解决方法,定义两个全局变量来记录构造和销毁的对象

如下,

思路就是这样的,但是我们知道c++对比c语言的地方是c++面向对象所以的功能都封装起来,这样用全局变量,有问题,每个人都可以更改。那我们怎么解决这个问题呢?

这里就要用到我们的static成员了

概念

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态的成员变量一定要在类外进行初始化

我们来看看怎么使用

这里为什么会报错啊?这里其实跟命名空间域类似,静态成员变量属于类域编译器是不会直接访问域中的数据,但是我们可以用一些突破类域的方法去访问

大家看这样是不是就可以访问到域中的数据了?

当然这里我们是令它为公有的才可以访问,

我们注意到为什么我们这里用空指针也可以访问到m和n,这么说m和n并没有存储在类中?

我们验证一下

这么看是不是说明m和n并没有存储在类中,其实m和n是属于静态变量存储在静态区中

那如果我们不是公有的,而是私有应该这么访问m和n,

这里我们可以创建函数来访问,或者通过函数来获取m和n的值。

我们还可以用静态成员函数来访问

它的特点是没有this指针,所以无法访问对象的成员变量,我们来验证一下

大家看是不是无法访问??

我们接下来看看静态成员变量的特性

特性

1. 静态成员为所有类对象所共享,不属于某个具体的实例

2. 静态成员变量必须在类外定义,定义时不添加static关键字

3. 类静态成员即可用类名::静态成员或者对象.静态成员来访问

4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员

5. 静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值

6,静态成员函数不可以调用非静态成员函数,非静态成员函数可以调用类的静态成员函数

友元

友元分为:友元函数和友元类

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

友元函数

我们来看下面这段代码

这里<<和>>为什么支持内置类型不支持自定义类型?

我们大家来看

这里支持内置类型不是直接支持而是对每个内置类型都进行了函数重载,以及运算符重载

大家看所以的内置类型都可以通过<<输出并且自动识别类型,本质是函数重载

那我们是不是也可以写一个函数来实现输出自定义类型的流插入

大家看为什么还是不行?

首先我们来分析<<这个是应该有两操作数并且位置应该对应,我们知道成员变量在调用成员函数是会隐藏地传一个this指针过去,这是this指针在右out在左是不是顺序不对啊,我们调换过来就行了

虽然可行但是,这样使用与我们平常的使用习惯不符,所以我们一个把他的位置调换,但是在类中this指针默认是在第一个,所以我们一个把函数定义在全局中。

这里我们又会遇到一个新的问题,我们定义在全局,无法访问到类的成员变量了。

这个时候我们友元函数就派上用场了。(不是只能用友元,只是一个例子)

这里的frend是一种声明,说明该函数可以访问类中的成员变量。

那接下来我们把>>也一起实现

说明:

友元函数可访问类的私有和保护成员,但不是类的成员函数

友元函数不能用const修饰

友元函数可以在类定义的任何地方声明,不受类访问限定符限制

一个函数可以是多个类的友元函数

友元函数的调用与普通函数的调用和原理相同

友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。

友元关系是单向的,不具有交换性。

比如Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time 类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。

友元关系不能传递

如果B是A的友元,C是B的友元,则不能说明C时A的友元。

注意,友元尽量不用

内部类

概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。

注意:此时这个内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去调用内部类。外部类对内部类没有任何优越的访问权限。

注意:内部类就是外部类的友元类。注意友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。

特性:

1. 内部类可以定义在外部类的public、protected、private都是可以的。

2. 注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名。

3. sizeof(外部类)=外部类,和内部类没有任何关系。

我们来一步一步验证

大家看B是A的内部类,只受A域,以及访问限定符的限制,A,B是两个独立的类

大家看在定义时受到了A域的限制

大家看这里我们可以看出B类默认时A类的友元类。

匿名对象

就是没有名字的对象,我们来看一下它的定义

从上面的代码中我们可以看到匿名对象与有名对象定义的不同

并且匿名对象的生命周期只有这一行,我们可以看到下一行他就会自动调用析构函数

那又同学可能要问了,匿名对象有什么用呢?

我们来想一个场景当我们只简单的需要调用类的一个成员函数时,我们就可以直接定义匿名对象直接调用。

我们只是简单调用,不需要定义一个有名对象。

注意:匿名对象,临时对象具有常性。

const可以延长匿名对象的声明周期

当A类型的引用出了作用域后A的匿名对象才调用析构函数。

   以上就是全部内容了,如果有错误或者不足的地方欢迎大家给予建议。 

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

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

相关文章

Web3技术解析:区块链在去中心化应用中的角色

引言 在过去几年中&#xff0c;Web3技术已经成为了互联网领域的一个热门话题。作为区块链技术的延伸&#xff0c;Web3不仅仅是数字货币的代名词&#xff0c;更是一个能够为各种应用提供去中心化解决方案的强大工具。本文将深入探讨区块链在Web3去中心化应用中的关键角色&#…

【考研数学】武忠祥考研课优缺点大盘点

虽然每年大家推荐的最多的是张宇和汤家凤&#xff0c;但是我强烈推荐武忠祥老师&#xff01; 武忠祥老师真宝藏老师&#xff0c;他讲课不像张宇老师那样段子频出&#xff0c;也不想汤家凤老师那样&#xff0c;武忠祥老师有自己的方法论&#xff0c;真的有点东西&#xff0c;武…

一周学会Django5 Python Web开发-Django5 ORM执行SQL语句

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

AI工具集:解锁智能新境界,一站式解决你的所有需求!

在这个信息爆炸的时代&#xff0c;我们每天都在与大量的数据和信息打交道。如何高效地处理这些信息&#xff0c;提高工作效率和生活品质&#xff0c;成为了我们亟待解决的问题。而AI工具集(AI-321.com)的出现&#xff0c;无疑为我们提供了一把解锁智能新境界的钥匙。 AI-321 | …

基于streamlit快速部署机器学习项目(Public URL)

基于streamlit的AIGC项目前端展示 1.Streamlit 简介与入门1.1 安装 Streamlit1.2 开发Streamlit应用程序1.3 启动并运行1.3.1 本地运行1.3.2 部署 现在LLM技术发展迅速&#xff0c;很多人在学习的时候&#xff0c;都想展示效果&#xff0c;并且想部署在服务器上&#xff0c;但是…

Zephyr sensor子系统学习

一、背景 2023年7月份nRF Connect SDK 2.4.0最新版本&#xff0c;使用的Zephyr V3.3版本。从Zephyr 3.5版本在子系统中加入了sensing子系统。 现在最新的nRF Connect SDK 2.6.0 release支持v3.5.99-ncs1&#xff0c;已经支持sensing子系统 nRF52840现在官方支持两个传感器de…

Rust中的函数指针

什么是函数指针 通过函数指针允许我们使用函数作为另一个函数的参数。函数的类型是 fn &#xff08;使用小写的 ”f” &#xff09;以免与 Fn 闭包 trait 相混淆。fn 被称为 函数指针&#xff08;function pointer&#xff09;。指定参数为函数指针的语法类似于闭包。 函数指…

阿里前端常考vue面试题汇总_阿里高级vue面试题

改变 ![](https://img-blog.csdnimg.cn/img_convert/b736620bcd29f08f3685022ab5583d8b.webp?x-oss-processimage/format,png)你会发现&#xff0c; **只有改变的栏目才闪烁&#xff0c;也就是进行重绘** &#xff0c;数据没有改变的栏目还是保持原样&#xff0c;这样就大大节…

(3)C程序可执行文件的生成过程

原文链接&#xff1a;https://www.jianshu.com/p/b7e44f749211 一、可执行文件的生成 我们先通过一个简单C程序&#xff0c;回顾一下可执行文件的生成过程。 ​​​​​​​ ​​​​​​​ 可执行文件的生成过程如下图&#xff1a; 如图&#xff0c;可执行文…

Java学习路线及自我规划

荒废了一段时间&#xff0c;这段时间的总结开始了JavaWeb的学习但是困难重重&#xff0c;例如Maven&#xff0c;Vue的路由等&#xff0c;所以我反省了一段时间&#xff0c;因为基础薄弱&#xff0c;加之学习的资源是速成视频&#xff0c;导致大厦将倾的局面&#xff08;也算不上…

为什么如果重写了某个类的equals方法,还必须重写对应的hashcode方法?

为什么如果重写了某个类的equals方法&#xff0c;还必须重写对应的hashcode方法&#xff1f; 答&#xff1a; 保证equals相同的两个对象hashcode必须相同的原则。不重写hashcode方法的的话&#xff0c;若用hashmap/hashset等散列表存储这个类&#xff0c;可能会出现两个相同对…

IDEA上配置Maven环境

1.选择IDEA中的Setting 2.搜索maven 3.设置IDEA使用本地安装的Maven&#xff0c;并修改配置文件路径 配置文件&#xff0c;本地仓库&#xff0c;阿里云仓库配置及路径教程 在IDEA上配置完成。

java中http调用组件深入详解

目录 一、前言 二、http调用概述 2.1 什么是http调用 2.1.1 http调用步骤 2.2 HTTP调用特点 2.3 HTTP调用应用场景 三、微服务场景下http调用概述 3.1 微服务开发中http调用场景 3.2 微服务组件中http的应用 四、常用的http调用组件 4.1 java中常用的http组件介绍 4…

输入输出重定向,追加重定向(Linux)

文章目录 一、输出重定向二、追加重定向三.输入重定向总结 一、输出重定向 我们在使用echo内容时&#xff0c;会把内容显示在显示器上。 echo自动换行。 我们如果输入 echo “hello linux” >file.txt 我们运行一下就会发现系统中多了一个file.txt的文件&#xff0c;如果这…

【C++打怪之路Lv3】-- 类和对象(上)

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;C打怪之路&#xff0c;python从入门到精通&#xff0c;数据结构&#xff0c;C语言&#xff0c;C语言题集&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文(平均质量分82)&#…

C++必修:类与对象(一)

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C学习 贝蒂的主页&#xff1a;Betty’s blog 1. 面向过程与面向对象 1.1. 面向过程 我们之前学习的C语言就是一种面向过程的语…

plsql 新建sql窗口 初始化慢的问题

问题描述&#xff1a; 新建sql窗口当sql语句多的情况下初始化很慢。 解决方法&#xff1a; 采用导入表的方式。 具体方式 工具->导入表->sql插入。 使用命令窗口 导入文件&#xff0c;然后点击导入按钮。

【力扣 Hot100 | 第七天】4.22(找到字符串中所有字母异位词)

文章目录 2.找到字符串中所有字母异位词2.1题目2.2解法&#xff1a;滑动窗口2.2.1解题思路2.2.2代码实现 2.找到字符串中所有字母异位词 2.1题目 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺…

Spring Security认证流程分析

我自己的思路 先分别实现 userdetailsService&#xff0c;userDetails&#xff0c;passwordEncoder三个接口&#xff0c; 然后就是写登录逻辑 本文章用的是继承UsernamePasswordAuthenticationFilter这个接口 因为这个框架默认登录逻辑是在这里面的&#xff0c;里面的核心就是…

vivado 使用“链路 (Links)”窗口查看和更改链路设置

使用“链路 (Links) ”窗口查看和更改链路设置 创建链路后 &#xff0c; 就会将其添加到“ Links ”视图 &#xff08; 请参阅下图 &#xff09; 中 &#xff0c; 该视图是更改链路设置和查看状态的主要方法 &#xff0c; 也是最佳方法。 “ Links ”窗口中的每一行都对应 1 …