【C++类和对象】初始化列表与隐式类型转换

news2024/9/29 23:30:26

💞💞 前言

hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹
在这里插入图片描述

💥个人主页:大耳朵土土垚的博客
💥 所属专栏:C++入门至进阶
这里将会不定期更新有关C++的内容,希望大家多多点赞关注收藏💖💖

目录

  • 💞💞 前言
  • 1.初始化列表
    • 1.1初始化列表定义
    • 1.2初始化列表原因
    • 1.3初始化列表注意点
  • 2. explicit关键字
    • 2.1explicit关键字定义
    • 2.2隐式类型转换
    • 2.3explicit关键字使用
  • 3.结语

1.初始化列表

1.1初始化列表定义

C++中的初始化列表是一种在对象构造函数中初始化成员变量的方法。它通过在构造函数的参数列表后面使用冒号来指定成员变量的初始化值,而不是在构造函数体内使用赋值语句来初始化。

在构造函数体内使用赋值语句来初始化:

class Date
{
public:
 Date(int year, int month, int day)
 {
 _year = year;
 _month = month;
 _day = day;
 }
private:
 int _year;
 int _month;
 int _day;
};

上述例子中我们使用构造函数对类的成员变量进行赋值;
虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。

初始化列表:

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

class Date
{
public:
	Date(int year, int month, int day)
	: _year(year)
	, _month(month)
	, _day(day)
	{}

private:
	int _year;
	int _month;
	int _day;
};

在上面的例子中,构造函数的初始化列表使用冒号 “:” 来指定成员变量 _year_month_day的初始值。在构造函数体内,不需要再使用赋值语句来初始化这些成员变量。

使用初始化列表可以提高代码执行效率,特别是在成员变量为对象类型时,可以避免多次调用默认构造函数和拷贝构造函数。

1.2初始化列表原因

在C++类和对象中有些成员变量必须定义的时候初始化,这时候如果只是简单的使用构造函数来赋值是不可行的,所以C++引入了初始化列表这个概念;

类中包含以下成员,必须放在初始化列表位置进行初始化:
1.引用成员变量
2.const成员变量
3.自定义类型成员(且该类没有默认构造函数时)

class A
{
public:
 	A(int a)
	 :_a(a)
	 {}
private:
 	int _a;
};
class B
{
public:
	 B(int a, int ref)
	 :_aobj(a)
	 ,_ref(ref)
	 ,_n(10)
	 {}
private:
	 A _aobj; // 没有默认构造函数
	 int& _ref; // 引用
	 const int _n; // const 
};
  • 在上面的例子中,常量成员变量 _n必须在构造函数的初始化列表中进行初始化,因为常量成员变量在对象创建后不能修改;
  • 引用成员变量 _ref 必须在构造函数的初始化列表中进行初始化,因为引用成员变量在创建后不能修改绑定的对象。
  • 没有默认构造函数的类类型成员变量_aobj:如果成员变量是一个类类型的对象,并且该类没有默认构造函数(无参构造函数),则必须在初始化列表中调用该类的有参构造函数进行初始化。

1.3初始化列表注意点

  1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
  2. 类中包含以下成员,必须放在初始化列表位置进行初始化:

引用成员变量
const成员变量
自定义类型成员(且该类没有默认构造函数时)

  1. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
    例如:
class Time
{
public:
	Time(int hour = 0)
	:_hour(hour)
	{
	cout << "Time()" << endl;
	}
private:
	int _hour;
};
class Date
{
public:
	Date(int day)
	{}
private:
	int _day;
	Time _t;
};
int main()
{
	Date d(1);
}

结果如下:
在这里插入图片描述

通过上述例子我们发现初始化列表是每个成员定义的地方,不管你写不写,每个成员都要走初始化列表,如果没写,对于内置类型给随机值,对于自定义类型会去调它的默认构造,走它自己的初始化列表;

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

例如:

class A
{
public:
	 A(int a)
 	:_a1(a)
	 ,_a2(_a1)
	 {}
 
	 void Print()
	 {
	 cout<<_a1<<" "<<_a2<<endl;
	 }
private:
	 int _a2;
	 int _a1;
};
int main()
{
	A aa(1);
 	aa.Print();
}

结果如下:
在这里插入图片描述

上述例子说明初始化列表的顺序是按照成员变量声明的顺序来的,首先先初始化_a2,这时_a1还没初始化是随机值,赋给_a2,所以_a2打印出来是随机值;然后再按照声明顺序初始化_a1为1;所以最终结果是1和随机值。

2. explicit关键字

2.1explicit关键字定义

在编程语言中,explicit是一个关键字,用于修饰构造函数,在对象初始化时明确地指定对象的类型,以防止隐式类型转换。使用explicit关键字可以禁止隐式转换,并要求使用显式的类型转换。

2.2隐式类型转换

我们先来了解一下什么是隐式类型转换?

隐式类型转换是指在表达式中,当操作数的类型与预期类型不匹配时,编译器自动将其转换为目标类型的过程。这种转换是自动进行的,不需要程序员显式地进行类型转换操作。
例如,当一个整数类型的值与一个浮点数类型的值进行运算时,编译器会自动将整数类型转换为浮点数类型,以便进行运算。

隐式类型转换可以方便地进行一些常见的类型转换,但也可能导致潜在的错误和不一致性。因此,在进行隐式类型转换时,程序员需要注意类型的兼容性和可能的风险。有时候,显式地进行类型转换会更加安全和清晰。

2.3explicit关键字使用

构造函数不仅可以构造与初始化对象,对于接收单个参数的构造函数,还具有类型转换的作用。

接收单个参数的构造函数具体表现:

  1. 构造函数只有一个参数
  2. 构造函数有多个参数,除第一个参数没有默认值外,其余参数都有默认值
  3. 全缺省构造函数

例如:

class Date
{
public:
	// 1. 单参构造函数,没有使用explicit修饰,具有类型转换作用	
	 Date(int year)
		:_year(year)
	{}
private:
	int _year;
	int _month;
	int _day;
};


void Test()
{
	Date d1(2022);
	// 用一个整形变量给日期类型对象赋值
	// 实际编译器背后会用2023构造一个无名对象,最后用无名对象给d1对象进行赋值
	d1 = 2023;
}

上述例子中单参构造函数,没有使用explicit修饰,具有类型转换作用,一旦使用了explicit修饰,就会编译不通过,例如:

class Date
{
public:
	// 1. 单参构造函数,没有使用explicit修饰,具有类型转换作用	
	explicit Date(int year)
		:_year(year)
	{}
private:
	int _year;
	int _month;
	int _day;
};

结果如下:
在这里插入图片描述

同样对于构造函数有多个参数,除第一个参数没有默认值外,其余参数都有默认值以及全缺省构造函数都具有类型转换的作用,一旦使用explicit修饰,就会禁止类型转换。

3.结语

初始化列表是C++类和对象中初始化成员变量的方式,在一些情况下可以提高效率和代码可读性。隐式类型转换在某些情况下可以方便地进行类型转换,但有时也会导致意外的结果或者不可预测的行为,所以C++提供了explicit来禁止隐式类型转换。
以上就是初始化列表与隐式类型转换所有的内容啦~ 完结撒花 ~🥳🎉🎉

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

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

相关文章

Canal1--搭建Canal监听数据库变化

1.安装mysql 默认安装了mysql&#xff08;版本8.0.x&#xff09;&#xff1b; 新创建用户 -- 创建用户 用户名&#xff1a;canal 密码&#xff1a;Canal123456 create user canal% identified by Canal123456;授权 grant SELECT, REPLICATION SLAVE, REPLICATION CLIENT on…

使用AOP切面做防止用户重复提交功能

在我们的项目中&#xff0c;需要考虑到有时候因为网络原因或者其他原因用户对同一个接口进行同一批数据的重复性操作&#xff0c;如果不做这样的处理很可能会在数据库中添加多条同样的数据。 我们可以通过使用aop来解决这样的问题&#xff0c;接下来看看具体怎么做吧~ 自定义…

c语言中,数组取地址的书写格式

数组取地址 为了更好的区分数组取地址时的情况&#xff0c;我们建立两个数组&#xff0c;arr1一维数组和arr2二维数组&#xff0c;用printf函数来打印出每个例子arr1和arr2的地址&#xff0c;这样可以更加直观的区分出来。 首先我们看到第一组打印&#xff0c;可以看到若是直接…

Python | Leetcode Python题解之第37题解数独

题目&#xff1a; 题解&#xff1a; class Solution:def solveSudoku(self, board: List[List[str]]) -> None:def dfs(pos: int):nonlocal validif pos len(spaces):valid Truereturni, j spaces[pos]for digit in range(9):if line[i][digit] column[j][digit] bloc…

jmeter 指定QPS压测接口

文章目录 jmeter 指定QPS压测接口更换语言为中文创建测试任务新建线程组右键线程组&#xff0c;新建http request&#xff0c;填写要你要压测的接口地址、参数如果需要自定义请求头&#xff0c;添加一个Http头信息管理器要查看结果和QPS统计数据&#xff0c;给上门的http请求添…

JVM虚拟机(十二)ParallelGC、CMS、G1垃圾收集器的 GC 日志解析

目录 一、如何开启 GC 日志&#xff1f;二、GC 日志分析2.1 PSPO 日志分析2.2 ParNewCMS 日志分析2.3 G1 日志分析 三、GC 发生的原因3.1 Allocation Failure&#xff1a;新生代空间不足&#xff0c;触发 Minor GC3.2 Metadata GC Threshold&#xff1a;元数据&#xff08;方法…

poll实现echo服务器的并发

poll实现echo服务器的并发 代码实现 #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <stdlib.h> #include <arpa/inet.h> #include <sys/time.h> #include <unistd.h> #…

c++的智能指针(5) -- weak_ptr

概述 我们在使用shared_ptr会出现以下的问题&#xff0c;会导致内存泄露。 代码1: 类内指针循环指向 #include <iostream> #include <memory>class B;class A { public:A() {std::cout << "Construct" << std::endl;}~A() {std::cout <…

基于开源CrashRpt与微软开源Detours技术深度改造的异常捕获库分享

目录 1、异常捕获模块概述 2、为什么需要异常捕获模块&#xff1f; 3、在有些异常的场景下是没有生成dump文件的 4、开源异常捕获库CrashRpt介绍 5、对开源库CrashRpt的改进 C软件异常排查从入门到精通系列教程&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持…

# 从浅入深 学习 SpringCloud 微服务架构(二)模拟微服务环境(1)

从浅入深 学习 SpringCloud 微服务架构&#xff08;二&#xff09;模拟微服务环境&#xff08;1&#xff09; 段子手168 1、打开 idea 创建父工程 创建 artifactId 名为 spring_cloud_demo 的 maven 工程。 --> idea --> File --> New --> Project --> Ma…

基于贝叶斯算法的机器学习在自动驾驶路径规划中的应用实例

目录 第一章 引言 第二章 数据准备 第三章 贝叶斯路径规划模型训练 第四章 路径规划预测 第五章 路径执行 第六章 实验结果分析 第一章 引言 自动驾驶技术的发展带来了自动驾驶车辆的出现&#xff0c;而路径规划作为自动驾驶车辆的关键功能之一&#xff0c;对于确定最佳行…

锐捷校园网自助服务系统 operatorReportorRoamService SQL注入漏洞致RCE漏洞复现

0x01 产品简介 锐捷校园网自助服务系统是锐捷网络推出的一款面向学校和校园网络管理的解决方案。该系统旨在提供便捷的网络自助服务,使学生、教职员工和网络管理员能够更好地管理和利用校园网络资源。 0x02 漏洞概述 锐捷校园网自助服务系统 operatorReportorRoamService 接…

STP学习的第一篇

1.STP的基本概念&#xff1a;根桥 &#xff08;1&#xff09;STP的主要作用之一是在整个交换网络中计算出一棵无环的“树”&#xff08;STP树&#xff09;。 &#xff08;2&#xff09;根桥是一个STP交换网络中的“树根”。 &#xff08;3&#xff09;STP开始工作后&#xf…

一、MinIO基本知识

MinIO基本知识 一、简介1.许可 二、部署1.Docker部署1.1 部署容器 1.2 MinIO页面访问1.3 创建Bucket![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/6c8aa92975f146b691f1f36ce1033e7c.png) 三、Python-API1.安装包2.Bucket、Object概念3.Bucket-API4.MinIOClient-…

【Yolov系列】Yolov5学习(一)补充1.2:自适应锚框计算详解+代码注释

一、自适应锚框计算详解 自适应锚框计算的具体过程&#xff1a; ①获取数据集中所有目标的宽和高。 ②将每张图片中按照等比例缩放的方式到 resize 指定大小&#xff0c;这里保证宽高中的最大值符合指定大小。 ③将 bboxes 从相对坐标改成绝对坐标&#xff0c;这里…

余氯控制器的功能优势简介

余氯控制器是一款智能化的水质监测设备&#xff0c;它采用高精度AD转换和单片机微处理技术&#xff0c;能够完成余氯值的高精度测量。这款控制器具备时间显示、数据存储等基本功能。 高智能化设计&#xff1a;余氯控制器采用了高精度AD转换和单片机微处理技术&#xff0c;确保…

VisualGLM-6B的部署步骤

对于如下命令&#xff0c;你将完全删除环境和环境中的所有软件包 conda remove -n env_name --all 一、VisualGLM-6B环境安装 1、硬件配置 操作系统&#xff1a;Ubuntu_64&#xff08;ubuntu22.04.3&#xff09; GPU&#xff1a;4050 显存&#xff1a;16G 2、配置环境 建…

防水型RTU IP68防水遥测终端机

在工业物联网的领域中&#xff0c;防水型RTU(Remote Terminal Unit)具有不可或缺的重要性。作为工业设备的守护神&#xff0c;它在实现数据采集和传输、远程控制和预警告警的同时&#xff0c;还能保障设备免受水分侵害&#xff0c;确保系统稳定安全的运行。    计讯物联防水…

JDK 11下载、安装、配置

下载 到Oracle管网下载JDK 11&#xff0c;下载前需要登录&#xff0c;否则直接点下载会出现502 bad gateway。 下载页面链接 https://www.oracle.com/hk/java/technologies/downloads/#java11-windows 登录 有些人可能没有Oracle账号&#xff0c;注册也比较慢&#xff0c;有需…

2024_GAMES101作业环境配置Mac(intel)_VSCode_Clion

目录 VSCodeClionCMakeList.txt VSCode brew install cmake 更换下载源为阿里云下载 opencv&#xff0c;不然会很慢 cd "$(brew --repo)" git remote -v cd "$(brew --repo)" git remote set-url origin https://mirrors.aliyun.com/homebrew/brew.git…