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

news/2024/5/19 6:01:05

💞💞 前言

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.mrgr.cn/p/48836406

相关文章

使用Python进行容器编排Docker Compose与Kubernetes的比较

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 随着容器化技术的普及&#xff0c;容器编排成为了管理和部署容器化应用程序的重要环节。在容…

SnakeYaml反序列化分析

前言 SnakeYaml是Java中解析yaml的库,而yaml是一种人类可读的数据序列化语言,通常用于编写配置文件等。yaml真是到哪都有啊。 环境搭建 <dependency><groupId>org.yaml</groupId><artifactId>snakeyaml</artifactId><version>1.32</v…

使用51单片机控制T0和T1分别间隔1秒2秒亮灭逻辑

#include <reg51.h>sbit LED1 P1^0; // 设置LED1灯的接口 sbit LED2 P1^1; // 设置LED2灯的接口unsigned int cnt1 0; // 设置LED1灯的定时器溢出次数 unsigned int cnt2 0; // 设置LED2灯的定时器溢出次数// 定时器T0 void Init_Timer0() {TMOD | 0x01;; // 定时器…

去除图像周围的0像素,调整大小

在做分割任务时&#xff0c;经常需要处理图像&#xff0c;如果图像周围有一圈0像素&#xff0c;需要去除掉&#xff0c;重新调整大小 数组的处理 如果图像的最外一圈为0&#xff0c;我们将图像最外圈的图像0去除掉。 import numpy as npdef remove_outer_zeros(arr):# 获取数…

定时器、PWM定时器、UART串口通信

我要成为嵌入式高手之4月15日ARM第八天&#xff01;&#xff01; ———————————————————————————— 定时器 S3C2440A 有 5 个 16 位定时器。其中定时器 0、1、2 和 3 具有脉宽调制&#xff08;PWM&#xff09;功能。定时器 4 是一个无 输出引脚的内部…

每日两题 / 438. 找到字符串中所有字母异位词 238. 除自身以外数组的乘积(LeetCode热题100)

438. 找到字符串中所有字母异位词 - 力扣&#xff08;LeetCode&#xff09; 记录p串每个字符出现次数 维护与p串等长的滑动窗口&#xff0c;记录其中每个字符的出现次数 每次滑动后将当前次数与p串的次数比较即可 class Solution { public:vector<int> findAnagrams(s…

Nginx第3篇-使用ngx_http_proxy_connect_module配置https正向代理

场景 我使用python爬虫&#xff0c;然后需要个代理&#xff0c;所以就用Nginx搭了一个代理服务器。对Nginx也不太熟&#xff0c;慢慢摸索&#xff0c;搭建完之后发现只能代理http的请求&#xff0c;无法穿透https。几经折腾和摸索发现一个强大的HTTP代理模块&#xff1a;ngx_h…

水资源管理系统:守护生命之源,构建和谐水生态

水资源是维系地球生态平衡和人类社会可持续发展的重要基础。然而,随着人口增长、工业化和城市化的加速,水资源短缺、水质污染和生态破坏等问题日益凸显。在这样的背景下,构建一个全面、高效、智能的水资源管理系统显得尤为迫切和必要。 项目背景 水资源的合理利用和有效保护…

Docker构建Golang项目常见问题

Docker构建Golang项目常见问题 1 Dockerfile1.1 dockerfile报错&#xff1a;failed to read expected number of bytes: unexpected EOF1.2 go mod tidy: go.mod file indicates go 1.21, but maximum supported version is 1.171.3 是否指定启动文件问题 2 构建及部署 1 Docke…

Unity3D 爆火的休闲益智游戏工程源码/3D资源 大合集

Unity3D休闲益智游戏工程源码大合集 一、关卡类游戏工程源码二、跑酷类游戏工程源码三、消除合成类游戏工程源码四、棋牌类游戏工程源码五、RPG(角色扮演)类游戏工程源码六、FPS&#xff08;射击&#xff09;类游戏工程源码十、Unity3D工艺仿真六、Unity游戏资源1、Unity3D 吃鸡…

vis.js外部自定义折线图

代码案例<!doctype html> <html> <head><title>Timeline</title><script type="text/javascript" src="https://unpkg.com/vis-timeline@latest/standalone/umd/vis-timeline-graph2d.min.js"></script><lin…

react native 安装app时报错 ”已安装了签名冲突的应用“

1. 问题描述: react native开发完app,手动安装app,报错”已安装了签名冲突的应用“。 或者执行命令安装npx react-native run-android --mode=release,报错2. 解决方法: 直接卸载原来的app发现无效,于是执行: adb uninstall "xxxxx"xxxxx换成你的app名,在这里…

SLS 查询新范式:使用 SPL 对日志进行交互式探索

在构建现代数据和业务系统的过程中,可观测性已经变得至关重要,日志服务(SLS)为 Log/Trace/Metric 数据提供了大规模、低成本、高性能的一站式平台服务,并提供数据采集、加工、投递、分析、告警、可视化等功能,从而全面提升企业在研发、运维、运营和安全等各种场景的数字化…

MySQL 基础语法(2)

文章目录 创建表查看表修改表表数据插入 本文为表结构相关的基础语言库相关的基础语句 创建表 CREATE TABLE table_name ( field1 datatype comment xxx, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎;CREATE TABLE&#xff1…

性能测试——压测工具locust——脚本初步编写

User Class 一个用户类代表一个用户(如果你愿意,也可以是一群蝗虫)。Locust 将为正在模拟的每个用户生成一个 User 类的实例。用户类可以定义一些通用属性。on_start 和 on_stop 方法 User和TaskSets可以声明一个on_start和on_stop方法, User:在该用户开始运行时调用on_st…

Qt-饼图示范

1.效果图 2.代码如下 2.1 .h文件 #ifndef PIECHARTWIDGET_H #define PIECHARTWIDGET_H#include <QWidget> #include <QChartView> #include <QPieSeries>#include<QVBoxLayout> #include<QMessageBox> #include <QtCharts>struct PieDat…

记录如何用php做一个网站访问计数器的方法

简介创建一个简单的网站访问计数器涉及到几个步骤,包括创建一个用于存储访问次数的文件或数据库表,以及编写PHP脚本来增加计数和显示当前的访问次数。方法以下是使用文件存储访问次数的基本步骤: 创建一个文本文件来存储计数:在网站的根目录下创建一个名为 counter.txt 的文…

截断堆积柱状图绘制教程

本教程原文链接&#xff1a;截断堆积柱状图绘制教程 欢迎大家转载&#xff01;&#xff01;&#xff01;&#xff01; 本期教程 写在前面 堆积柱状图是柱状图的常见类型之一&#xff0c;也是平时使用概率较高的图形之一。我们前期发布了很多个柱状图的绘制教程&#xff0c;若你…