【C++】再识构造函数:初始化列表新方式

news2024/11/23 11:39:47

欢迎来到CILMY23的博客

🏆本篇主题为: 再识构造函数:初始化列表新方式

🏆个人主页:CILMY23-CSDN博客

🏆系列专栏:Python | C++ | C语言 | 数据结构与算法 | 贪心算法 | Linux

🏆感谢观看,支持的可以给个一键三连,点赞关注+收藏。


写在前头:

在之前我们花了大篇幅了解了构造函数,包括但不限于构造函数的详解,构造函数和析构函数的顺序,以及构造函数中特殊的拷贝构造函数。那这次的构造函数又会带给我什么惊喜呢?


目录

再见构造函数

1️⃣ 构造函数赋值

2️⃣ 初始化列表的概念

3️⃣ 为什么会有初始化列表? 

4️⃣ 初始化列表的特点 

5️⃣ 构造函数新的写法

6️⃣ explicit关键字 

7️⃣ 多参数类型的隐式转换 


再见构造函数

1.1  构造函数赋值

在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。

class Student
{
public:
	//无参构造函数
	Student()
	{
		strcpy(_name, "xxxxxx");
		_age = 0;
		strcpy(_ID, "xxxxxxx");
	}
	void Print()
	{
		cout << "学生姓名:" << _name << endl;
		cout << "学生年龄:" << _age << endl;
		cout << "学生学号:" << _ID << endl;
	}
private:
	char _name[20];
	int _age;
	char _ID[20];
};

int main()
{
	Student stu1;//调用了无参的构造函数
	stu1.Print();

	return 0;
}

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

1.2  初始化列表的概念

初始化列表是C++中的一个功能,允许在构造函数中直接初始化成员变量,而非在构造函数体内赋值。初始化列表直接跟在构造函数的参数列表后面,以冒号开始后面紧跟一个或多个用逗号分隔的初始化表达式。这些表达式直接对成员变量或自定义类型进行初始化。

例如:这里有个学生类,我们要用初始化列表。(在这里对字符的拷贝我们仍然采用C的方法来实现,利用strncpy或者strcpy,在之后我们会用string来实现这些)

class Student {
public:
    // 使用初始化列表来初始化_age
    Student(const char* name, int age, const char* ID) 
        : _age(age) 
    {
        // 为_name和_ID赋值
        strncpy(_name, name, sizeof(_name) - 1);
        _name[sizeof(_name) - 1] = '\0'; 
        strncpy(_ID, ID, sizeof(_ID) - 1);
        _ID[sizeof(_ID) - 1] = '\0'; 
    }

private:
    char _name[20];
    int _age;
    char _ID[20];
};

int main()
{
    Student student1("Alice", 20, "1234567890");

    student1.Print();

    return 0;
}

1.3 为什么会有初始化列表? 

 例如:就像下面这段代码一样,有些类的成员是必须要在初始化的时候定义的,这里的_n = -1;是会报错的。就比如const成员是这样的。那哪个地方是初始化的呢?那它就需要去构造函数去找空间给它初始化,但也会有安全性的问题,所以有了初始化列表这个概念。初始化列表是每个成员变量定义初始化的位置。

顺序是先走上面的初始化列表,然后再走函数体内的赋值修改,能用初始化列表就用初始化列表。

class Student 
{
public:
    
    //Student(const char* name, int age, const char* ID) 
    //    : _age(age) 
    //{
    //    //赋值修改
    //    strncpy(_name, name, sizeof(_name) - 1);
    //    _name[sizeof(_name) - 1] = '\0'; 
    //}

    //构造函数
    Student(const char* name, int age)
    {
        strncpy(_name, name, sizeof(_name) - 1);
        _name[sizeof(_name) - 1] = '\0';

        _age = age;

       _n = -1; // 无法修改
    }

private:
    //声明
    char _name[20];
    int _age = 1; //缺省值

    const int _n;
};

int main() 
{
    //对象实例化
    Student student1("Alice", 20);

    return 0;
}

1.4 初始化列表的特点 

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

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

  3. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量, 一定会先使用初始化列表初始化。
  4. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后 次序无关 

这些特点如下所示: 

class A
{
public:
    A(int x)
        //初始化列表
        :_a(1)
    {
        //赋值修改
        _a = x;
    }

private:
    int _a;
};


class Student
{
public:
    //初始化列表是每个成员变量定义初始化的位置
    //能用初始化列表就用初始化列表
    Student(const char* name, int age, int &x)
        : _age(age)
        , _n(1)
        , _aa(1)//显式调用构造函数
        , ref(x)
    {
        strncpy(_name, name, sizeof(_name) - 1);
        _name[sizeof(_name) - 1] = '\0'; 
    }

private:
    //声明
    char _name[20];
    int _age = 1; //缺省值

    //必须走初始化列表
    //1. const 成员 
    //2. 引用成员变量
    //3. 自定义类型成员
    const int _n;
    int& ref;
    A _aa;
};

int main()
{
    //对象实例化
    int x = 0;
    Student student1("Alice", 20,x);

    return 0;
}

 1.5 构造函数新的写法

构造函数结合初始化列表后,我们可以写成main函数中的另外两种cc的形式。 

class C
{
public:
	C(int x = 0)
		:_x(x)
	{}
private:
	int _x;
};

class B
{
public:
	B()
		:_p(2)
		,_p1((int*)malloc(sizeof(4)*10))
	{
		if (_p1 == nullptr)
		{
			perror("malloc fail");
		}
	}
private:
	//缺省值是给初始化列表的
	int _p = 1;
	int* _p1 = (int*)malloc(sizeof(4));
};

int main()
{
	B bb;
	//构造函数的写法
	C cc1(1);
	//2构造一个临时对象,再拷贝构造
	C cc2 = 2;

	return 0;
}

 其实通过这个例子我们可以发现,单参数构造函数支持隐式类型的转换,2构造一个临时对象,然后再拷贝构造

如果遇到同一个表达式连续步骤的构造,一般会被编译器优化。 

隐式类型转换是有好处的,例如我们在栈传参的时候,可以直接将int类型的4转换成自定义类型。

1.6 explicit关键字 

如果你不想让上述这种隐式类型转换发生,那你就可以加一个关键字 - explicit。 

  

1.7 多参数类型的隐式转换 

在目前的C++11中,支持多参数类型的隐式转换,C++98还不支持,用花括号括起来。


总结:

  • 初始化列表直接跟在构造函数的参数列表后面,以冒号开始后面紧跟一个或多个用逗号分隔的初始化表达式
  • 顺序是先走上面的初始化列表,然后再走函数体内的赋值修改
  • 当出现函数赋值修改缺省值,和初始化列表的时候,推荐是能用初始化列表就用初始化列表。
  • 有些成员必须走初始化列表,1. const 成员 2. 引用成员变量 3. 自定义类型成员(没有默认构造的自定义类型成员)
  • 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后 次序无关
  • 缺省值是给初始化列表的
  • 单参数构造函数支持隐式类型的转换
  • 临时变量具有常性,需要加const修饰。
  • 构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值的构造函数,还具有类型转换的作用。
  • explicit 可以限制隐式类型的转换
  • C++11 支持多参数类型的隐式类型转换

感谢各位同伴的支持,本期C++就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞,关注+收藏,若有不足,欢迎各位在评论区讨论。  

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

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

相关文章

【实践】使用vscode来debug go程序的尝鲜

配置 首先&#xff0c;当然得配置好vscode 的go环境&#xff0c; 装个go插件就基本满足了 配置 launch.json, 可以配置多个环境的程序启动参数&#xff08;很友好&#xff09; {"version": "0.2.0","configurations": [{"name": &…

C++深度解析教程笔记8

C深度解析教程笔记8 第17课 - 对象的构造&#xff08;上&#xff09;类定义中成员变量i和j的初始值&#xff1f;实验-成员变量的初始值对象初始化解决方案1实验-手动调用函数初始化对象对象初始化解决方案2&#xff1a;构造函数实验-构造函数小结 第18课 - 对象的构造&#xff…

乡村振兴的乡村人才振兴计划:培养乡村人才,吸引人才回流,激发乡村发展活力,为美丽乡村建设提供人才保障

目录 一、引言 二、乡村人才振兴计划的必要性 &#xff08;一&#xff09;乡村发展面临的人才困境 &#xff08;二&#xff09;人才振兴对乡村振兴的推动作用 三、乡村人才振兴计划的实施路径 &#xff08;一&#xff09;加强乡村教育体系建设 &#xff08;二&#xff0…

AD软件针对分散的元器件归一排列

先框选 然后快捷键TOL 绿色的十字箭头选框选位置 完成

Golang | Leetcode Golang题解之第87题扰乱字符串

题目&#xff1a; 题解&#xff1a; func isScramble(s1, s2 string) bool {n : len(s1)dp : make([][][]int8, n)for i : range dp {dp[i] make([][]int8, n)for j : range dp[i] {dp[i][j] make([]int8, n1)for k : range dp[i][j] {dp[i][j][k] -1}}}// 第一个字符串从 …

deveco studio 打开官方案例,不显示运行按钮。

就拿官方的search举例好了 git 地址 https://gitee.com/harmonyos/samples/tree/master/ETSUI/Search 使用deveco studio打开Search项目&#xff0c;打开Tools->Device-Manager中的Local Emulator本地模拟器&#xff0c; 此时会发现&#xff0c;运行按钮是灰色的&#xff0…

【前端性能优化】深入解析重绘和回流,构建高性能Web界面

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 &#x1f3af; 引言&#xff1a;探索Web性能的基石&#x1f3d7;️ 基础概念&#xff1a;什么是重绘和回流&#xff1f;&#x1f4cc; 回流&#xff08;Reflow&#xff09;&#x1f4cc; 重绘&#xff08;Repaint&#xff0…

阿赵UE引擎C++编程学习笔记——解决中文乱码问题

大家好&#xff0c;我是阿赵。   在UE编写C的时候&#xff0c;可能有些朋友发现&#xff0c;在C里面如果打印输出或者赋值一些中文的字符串的时候&#xff0c;会出现各种的报错&#xff0c;要么乱码&#xff0c;要么直接编译不过。   这个问题&#xff0c;其实和UE本身没什…

数字化信息协同助力智能巡查,基于YOLOv5全系列【n/s/m/l/x】参数模型开发构建无人机数字侦查场景下智能靶标检测识别系统

无人机的快速发展与普及&#xff0c;使得其进入千家万户各行各业&#xff0c;发挥着越来越重要的作用。随着科技的飞速发展&#xff0c;未来的数字信息化战场正逐渐展现出其独特的作战形态。在这个以数据和信息为主导的新战场上&#xff0c;无人机侦查手段与人工智能目标智能检…

vue3编译优化之“静态提升”

前言 在上一篇 vue3早已具备抛弃虚拟DOM的能力了文章中讲了对于动态节点&#xff0c;vue做的优化是将这些动态节点收集起来&#xff0c;然后当响应式变量修改后进行靶向更新。那么vue对静态节点有没有做什么优化呢&#xff1f;答案是&#xff1a;当然有&#xff0c;对于静态节…

AI论文写作生成器-AI自动生成论文-10分钟/万字论文

在当今这个高速发展的信息时代&#xff0c;科技的进步无疑给我们的工作、学习乃至生活带来了翻天覆地的变化。学术研究领域也不例外&#xff0c;近期一款新型的论文自动写作神器诞生了&#xff0c;它凭借人工智能技术的优势&#xff0c;为学者和研究人员撰写学术论文提供了极大…

每日一题11:Pandas:数据重塑-透视

一、每日一题 解答&#xff1a; import pandas as pddef pivotTable(weather: pd.DataFrame) -> pd.DataFrame:df_pivot weather.pivot(indexmonth, columnscity, valuestemperature)return df_pivot 题源&#xff1a;力扣 二、总结 Pandas 是一个强大的 Python 数据分析…

ANSYS Workbench中如何从面选择创建节点集合named selection?

点击选中一个面&#xff0c;右键named selection&#xff1a;

windows下安装redis

正常生产我们会在Linux下安装redis&#xff0c;windows下安装redis只做依赖环境的快速搭建、项目的快速验证。 1、下载地址 Releases microsoftarchive/redis GitHub 下载 Redis-x64-3.0.504.zip 2、解压文件夹 解压到本地某个文件夹下&#xff0c;比如 D:\redis-3.0.504 3…

STL---排序模板参数

map 对map进行排序 首先一定要注意map模板类的第三个模板参数&#xff0c;这个参数决定元素按键值升序或者降序在map中的存储方式&#xff1a; 默认&#xff1a;less<key>升序----- < -----第一个小于取第一个 可设置&#xff1a;greater<key>降序-------…

机器人系统ros2-开发学习实践11-从零开始构建视觉机器人模型(urdf)(02)

接上一个教程继续完善&#xff0c; 我们需要对机器人身体的蓝色&#xff0c;我们定义了一种名为“蓝色”的新材质&#xff0c;其中红色、绿色、蓝色和 alpha 通道分别定义为 0、0、0.8 和 1。所有值都可以在 [0,1] 范围内。然后该材料由 base_link 的视觉元素引用。白色材料的…

移动 App 入侵与逆向破解技术-iOS 篇

如果您有耐心看完这篇文章&#xff0c;您将懂得如何着手进行app的分析、追踪、注入等实用的破解技术&#xff0c;另外&#xff0c;通过“入侵”&#xff0c;将帮助您理解如何规避常见的安全漏洞&#xff0c;文章大纲&#xff1a; 简单介绍ios二进制文件结构与入侵的原理介绍入…

【C++】可变参数模板简单介绍

前言 可变参数模板是C11中的新特性&#xff0c;它能够让我们创建可以接收可变参数的函数模板和类模板&#xff0c;相比C98/03&#xff0c;类模版和函数模版中只能含固定数量的模版参数&#xff0c;可变模版参数是一个巨大的改进&#xff0c;通过系统系统推演数据的类型&#xf…

【论文阅读笔记】HermesSim(Code is not Natural Language) (Security 24)

个人博客地址 HermesSim [Security 24] 论文&#xff1a;《Code is not Natural Language: Unlock the Power of Semantics-Oriented Graph Representation for Binary Code Similarity Detection》 仓库&#xff1a;https://github.com/NSSL-SJTU/HermesSim 提出的问题 二…