【C++】类和对象(3)--初始化列表(再谈构造函数)

目录

一 引入

二 初始化列表概念

三 初始化列表特性

1 引用和const

2 混合使用

3 自定义成员情况

四 初始化列表中的初始化顺序

五 总结


一 引入

构造函数体赋值

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;//}Date(int year, int month, int day):_year(year), _month(month), _day(day){// 初始化列表}void Print(){cout << _year << '/' << _month << '/' << _day << endl;}private:// 声明int _year; int _month;int _day;
};

上面的例子中两个构造函数的结果是一样的。上面的构造函数(使用初始化列表的构造函数)显式的初始化类的成员;而没使用初始化列表的构造函数是对类的成员赋值,并没有进行显式的初始化。

初始化和赋值对内置类型的成员没有什么大的区别,像上面的任一个构造函数都可以。对非内置类型成员变量,为了避免两次构造,推荐使用类构造函数初始化列表。但有的时候必须用带有初始化列表的构造函数

三 初始化列表特性

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

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

引用成员变量

const成员变量

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

总之 这三类不能在函数内部初始化

1 引用和const

class Date{public:Date(int year, int month, int day){// 函数体内初始化_year = year;_month = month;_day = day;int& _ref;//引用 -->errorconst int _n;//const -->error}void Print(){cout << _year << '/' << _month << '/' << _day << endl;}private:// 声明int _year; // 缺省值int _month;int _day;int& _ref;//引用const int _n;//const};

这是为什么?

引用和const只能初始化而不是赋值

之前有讲过,若是我们自己不去实现构造函数的话,类中会默认提供一个构造函数来初始化成员变量,对于【内置类型】的变量不会处理,对【自定义类型】的变量会去调用它的构造函数。那么对于这里的_year, _month, _day, _ref, _n都属于内置类型的数据,所以编译器不会理睬,可是引用变量, const修饰的变量又必须要初始化,所以初始化列表诞生

有人说给个缺省值不就好了 这个办法确实是可以解决我们现在的问题,因为C++11里面为内置类型不初始化打了一个补丁,在声明的位置给到一个初始化值,就可以很好地防止编译器不处理的问题

但是现在我想问一个问题:如果不使用这个办法呢?你有其他方法吗?难道C++11以前就那它没办法了吗?

改正如下:

class Date
{
public://Date(int year, int month, int day)//{//    // 函数体内初始化//    _year = year;//    _month = month;//    _day = day;//     int& _ref;//引用 -->error//     const int _n;//const -->error//}Date(int year, int month, int day):_year(year), _month(month), _day(day), _ref(year), _n(1){// 初始化列表}void Print(){cout << _year << '/' << _month << '/' << _day << endl;}private:// 声明int _year; // 缺省值int _month;int _day;int& _ref;//引用const int _n;//const
};

2 混合使用

当然函数体内初始化和初始化列表可以混着用

Date(int year, int month, int day): _ref(year), _n(1){// 函数体内初始化_year = year;_month = month;_day = day;}

3 自定义成员情况

class A
{
public:A(int a = 0)//默认构造:_a(a){cout << "A(int a = 0)" << endl;}
private:int _a;
};class Date
{
public:Date(int year, int month, int day){// 函数体内初始化_year = year;_month = month;_day = day;}private:// 声明int _year; int _month;int _day;A _aa;//调用默认构造
};int main()
{Date d(2023, 11, 14);return 0;
}

1 如果A没有默认构造呢? -->初始化列表

class A
{
public:A(int a)//这不是默认构造:_a(a){cout << "A(int a = 0)" << endl;}
private:int _a;
};class Date
{
public:Date(int year, int month, int day):_aa(10){// 函数体内初始化_year = year;_month = month;_day = day;}private:// 声明int _year; int _month;int _day;A _aa;//没有默认构造
};int main()
{Date d(2023, 11, 14);return 0;
}

2 如果不想使用A的默认构造的值呢?-->初始化列表

class A
{
public:A(int a = 10)//默认构造:_a(a){cout << "A(int a = 0)" << endl;}
private:int _a;
};class Date
{
public:Date(int year, int month, int day):_aa(1000){// 函数体内初始化_year = year;_month = month;_day = day;}private:// 声明int _year; int _month;int _day;A _aa;//调用默认构造
};int main()
{Date d(2023, 11, 14);return 0;
}

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

四 初始化列表中的初始化顺序

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

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还没有初始化, 给的随机值,.

五 总结

初始化列表解决的问题:

1、必须在定义的地方显示初始化 引用 const 没有默认构造自定义成员

2、有些自定义成员想要显示初始化,自己控制

尽量使用初始化列表初始化

构造函数能不能只要初始化列表,不要函数体初始化?

不能,因为有些初始化或者检查的工作,初始化列表也不能全部搞定

80-100%初始化列表搞定,还有需要用函数体,他们可以混着用

我们来看看下面这段代码

class Stack
{
public:Stack(int n = 2):_a((int*)malloc(sizeof(int)* n)), _top(0), _capacity(n){//...//cout << "Stack(int n = 2)" << endl;if (_a == nullptr){perror("malloc fail");exit(-1);}memset(_a, 0, sizeof(int) * n);}//...int* _a;int _top;int _capacity;
};class MyQueue
{
public:MyQueue(int n1 = 10, int n2 = 20)//形成默认构造函数:_s1(n1), _s2(n2){}private:Stack _s1;Stack _s2;int _size = 0;
};int main()
{MyQueue q1;MyQueue q2(100, 100);//有初始化列表那就先走初始化列表return 0;
}

这样我们就能控制我们怎样控制我们的默认构造.

这节是对上一节类和对象(2)构造函数的续集, 建议两个章节要有先后理解, 本节内容比较简单, 注重理解 上一节的博客【C++】类和对象(2)--构造函数-CSDN博客

析构函数 【C++】类和对象(4)--析构函数-CSDN博客

继续加油!  

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

初学UE5 C++①

游戏类 1.创建所需项的类 2.创建游戏模式类&#xff0c;在该类上实现所需项&#xff0c;引入头文件和构造函数时实例化 三种时间函数类型函数和提示类型 FName、FString、FText类型相互转化 FName用FName FString用ToString&#xff08;&#xff09; FText用FText&#xff1a;…

让AI拥有人类的价值观,和让AI拥有人类智能同样重要

编者按&#xff1a;2023年是微软亚洲研究院建院25周年。25年来&#xff0c;微软亚洲研究院探索并实践了一种独特且有效的企业研究院的新模式&#xff0c;并以此为基础产出了诸多对微软公司和全球社会都有积极影响的创新成果。一直以来&#xff0c;微软亚洲研究院致力于创造具有…

RabbitMQ的 五种工作模型

RabbitMQ 其实一共有六种工作模式&#xff1a; 简单模式&#xff08;Simple&#xff09;、工作队列模式&#xff08;Work Queue&#xff09;、 发布订阅模式&#xff08;Publish/Subscribe&#xff09;、路由模式&#xff08;Routing&#xff09;、通配符模式&#xff08;Topi…

Spring Framework 核心容器详解:Core、Beans、Context 和 Expression Language 模块

Spring可能成为您的所有企业应用程序的一站式商店。但是&#xff0c;Spring是模块化的&#xff0c;允许您挑选适用于您的模块&#xff0c;而无需引入其他模块。下面的部分提供了Spring Framework中所有可用模块的详细信息。 Spring Framework提供了大约20个模块&#xff0c;可…

黑马程序员微服务第四天课程 分布式搜索引擎1

分布式搜索引擎01 – elasticsearch基础 0.学习目标 1.初识elasticsearch 1.1.了解ES 1.1.1.elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎&#xff0c;具备非常多强大功能&#xff0c;可以帮助我们从海量数据中快速找到需要的内容 例如&#xff1a; …

单pipeline部署一套代码,多项目

单pipeline部署一套代码&#xff0c;多项目 pipeline {agent anyparameters {gitParameter(name: BRANCH_TAG, type: PT_BRANCH_TAG, branchFilter: origin/(.*), defaultValue: main, selectedValue: DEFAULT, sortMode: DESCENDING_SMART, description: 请选择需要部署的代码…

时间序列预测各类算法探究上篇

前言&#xff1a; 最近项目需要对公司未来业绩进行预测&#xff0c;以便优化决策&#xff0c;so 研究一下时序算法。纯个人理解&#xff0c;记录以便备用&#xff08;只探究一下原理&#xff0c;所有算法都使用基本状态&#xff0c;并未进行特征及参数优化&#xff09;。 环境…

Oracle(2-2)Oracle Net Architecture

文章目录 一、基础知识1、Oracle Net Connections Oracle网络连接2、C/S Application Connection C/S应用程序连接3、OSI Communication Layers OSI通信层4、Oracle Protocol Support Oracle协议支持5、B/S Application Connections B/S应用程序连接6、TwoTypes JDBC Drivers 两…

npm封装插件打包上传后图片资源错误

问题&#xff1a; npm封装插件&#xff1a;封装的组件页面涉及使用图片资源&#xff0c;在封装的项目里调用图片显示正常&#xff1b;但是打包上传后&#xff0c;其他项目引入使用报错找不到图片资源&#xff1b;图片路径也不对 获取图片的base64方法 解决方案&#xff1a; 将…

3.4 Linux 软件管理

一. RPM 软件包管理器 1、软件包介绍 RPM&#xff08;RedHat Package Manager&#xff09;软件包&#xff1a;扩展名为“.rpm”。RPM本质上就是一个包&#xff0c;包含可以立即在特定机器体系结构上安装和运行的Linux软件。安装RPM软件包需要使用rpm命令或yum命令。 源代码软…

PC端微信@所有人逻辑漏洞

&#xff08;一&#xff09;过程 这个漏洞是PC端微信&#xff0c;可以越权让非管理员艾特所有人&#xff0c;具体步骤如下 第一步&#xff1a;找一个自己的群&#xff08;要有艾特所有人的权限&#xff09;“123”是我随便输入的内容&#xff0c;可以更改&#xff0c;然后按c…

Mac M3 芯片安装 Nginx

Mac M3 芯片安装 Nginx 一、使用 brew 安装 未安装 brew 的可以参考 【Mac 安装 Homebrew】 或者 【Mac M2/M3 芯片环境配置以及常用软件安装-前端】 二、查看 nginx 信息 通过命令行查看 brew info nginx可以看到 nginx 还未在本地安装&#xff0c;显示 Not installed …

百望云斩获“新华信用金兰杯”ESG优秀案例 全面赋能企业绿色数字化

近年来&#xff0c;中国ESG蓬勃发展&#xff0c;在政策体系构建、ESG信披ESG投资和国际合作等方面都取得了阶段性成效&#xff0c;ESG生态不断完善。全社会对ESG的认识及实践也在不断深化&#xff0c;ESG实践者的队伍在不断发展壮大。 ESG作为识别企业高质量发展的重要指标&…

Kafka(三)生产者发送消息

文章目录 生产者发送思路自定义序列化类配置生产者参数提升吞吐量 发送消息关闭生产者结语示例源码仓库 生产者发送思路 如何确保消息格式正确的前提下最终一定能发送到Kafka? 这里的实现思路是 ack使用默认的all开启重试在一定时间内重试不成功&#xff0c;则入库&#xff…

VS Code画流程图:draw.io插件

文章目录 简介快捷键 简介 Draw.io是著名的流程图绘制软件&#xff0c;开源免费&#xff0c;对标Visio&#xff0c;用过的都说好。而且除了提供常规的桌面软件之外&#xff0c;直接访问draw.io就可以在线使用&#xff0c;堪称百分之百跨平台&#xff0c;便捷性直接拉满。 那么…

TOUGH系列软件教程

查看原文>>>全流程TOUGH系列软件实践技术应用 TOUGH系列软件是由美国劳伦斯伯克利实验室开发的&#xff0c;旨在解决非饱和带中地下水、热运移的通用模拟软件。和传统地下水模拟软件Feflow和Modflow不同&#xff0c;TOUGH系列软件采用模块化设计和有限积分差网格剖分…

(八)Spring源码解析:Spring MVC

一、Servlet及上下文的初始化 1.1> DispatcherServlet的初始化 对于Spring MVC来说&#xff0c;最核心的一个类就是DispatcherServlet&#xff0c;它负责请求的行为流转。那么在Servlet的初始化阶段&#xff0c;会调用init()方法进行初始化操作&#xff0c;在DispatcherSe…

第三天课程 RabbitMQ

RabbitMQ 1.初识MQ 1.1.同步和异步通讯 微服务间通讯有同步和异步两种方式&#xff1a; 同步通讯&#xff1a;就像打电话&#xff0c;需要实时响应。 异步通讯&#xff1a;就像发邮件&#xff0c;不需要马上回复。 两种方式各有优劣&#xff0c;打电话可以立即得到响应&am…

数据库事务相关问题

1. 什么是数据库事务&#xff1f; 事务&#xff0c;由一个有限的数据库操作序列构成&#xff0c;这些操作要么全部执行,要么全部不执行&#xff0c;是一个不可分割的工作单位。 假如A转账给B 100 元&#xff0c;先从A的账户里扣除 100 元&#xff0c;再在 B 的账户上加上 100 …