【C++】构造函数和析构函数第三部分(各种构造函数调用规则、多个对象的构造和析构、初始化列表)--- 2023.11.6

目录

      • 各种构造函数的调用规则
        • 对象以值的方式给函数参数
        • 用一个已有的对象去初始化另一个对象
        • 函数的局部对象以值的方式从函数返回
        • 调用规则1
        • 调用规则2
      • 多个对象的构造和析构
      • 初始化列表
      • 结束语

各种构造函数的调用规则

对象以值的方式给函数参数

实例:

class Maker
{
public:Maker(){cout << "无参构造函数" << endl;}Maker(int a){cout << "有参构造函数" << endl;}Maker(const Maker &maker){cout << "拷贝构造函数" << endl;}~Maker(){cout << "析构函数" << endl;}
};void func(Maker m)
{}void test01()
{Maker m1;func(m1);}

对上述代码进行分析:

Maker m1;

实例化对象,并且该对象名为m1,在实例化对象过程中会调用Maker类中的无参构造。

func(m1);

该func函数中的形参为Maker m,并且传入该函数的形参为刚刚实例化完成的对象m1,所以实际上为Maker m = m1。即会调用Maker类中的拷贝构造函数。

最后在完成该函数生命周期时,会相反顺序依次调用析构函数来完成释放。

代码运行结果如下:

在这里插入图片描述

用一个已有的对象去初始化另一个对象

实例:

void test02()
{Maker m1;Maker m2(m1);
}

对上述代码进行分析:

Maker m1;

实例化对象,并且该对象名为m1,在实例化对象过程中会调用Maker类中的无参构造。

Maker m2(m1);

相当于调用Maker类中的拷贝构造函数。

代码运行结果如下:
在这里插入图片描述

函数的局部对象以值的方式从函数返回

实例:

Maker func2()
{//局部对象Maker m;cout << "局部对象的地址:" << &m << endl;return m;
}void test03()
{Maker m1 = func2();cout << "m1对象的地址:" << &m1 << endl;
}

对上述代码进行分析:

func2函数的主要作用为将实例化成功的对象m的地址打印出来,并且将该对象作为该函数的返回值。

Maker m1 = func2();

将func2()的函数的返回值传递给m1,并且打印m1的地址。理论上m1和m的地址是一样的。

代码运行结果如下:
在这里插入图片描述

调用规则1

如果程序员提供了有参构造,那么编译器不会提供默认构造函数,但是会提供默认的拷贝构造

实例:

class Maker
{
public:Maker(){cout << "无参构造函数" << endl;}Maker(int a){cout << "有参构造函数" << endl;}~Maker(){cout << "析构函数" << endl;}
};void test01()
{Maker m(10);Maker m2(m);
}

对上述代码进行分析:

Maker m(10);

调用Maker类中的有参构造函数,即a = 10

Maker m2(m);

使用该函数将会调用拷贝构造函数,但是我们发现在Maker类中并没有创建拷贝构造函数,我们先试试看程序能不能正常运行?

代码运行结果如下:
在这里插入图片描述
由上述可知,代码可以正常运行,并没有报错,这是因为编译器会提供默认的拷贝构造函数,只不过这个拷贝构造函数不做任何处理。

调用规则2

如果程序员提供了拷贝构造函数,那么编译器不会提供默认的构造函数和默认的拷贝构造函数

实例:

class Maker
{
public:Maker(const Maker& maker){cout << "拷贝构造函数" << endl;}~Maker(){cout << "析构函数" << endl;}
};void test02()
{Maker m;
}

对上述代码进行分析:

Maker m;

实例化对象m时,会自动调用构造函数,但是我们发现在Maker类中创建了拷贝构造函数,我们先试试看代码能不能正常运行?

代码运行结果如下:

在这里插入图片描述
从上可知,代码并不能正常运行,即我们可以得知,当提供了拷贝构造函数,那么编译器不会提供默认的构造函数和默认的拷贝构造函数。

多个对象的构造和析构

实例:

class BMW
{
public:BMW(){cout << "BMW构造" << endl;}~BMW(){cout << "BMW析构" << endl;}
};class Buick
{
public:Buick(){cout << "Buick构造" << endl;}~Buick(){cout << "Buick析构" << endl;}
};class Maker
{
public:Maker(){cout << "Maker构造" << endl;}~Maker(){cout << "Maker析构" << endl;}
private:Buick bui;//成员对象BMW bmw;//成员对象
};void test01()
{Maker m;
}

对上述代码进行分析:

private:Buick bui;BMW bmw;

在之前的实例中,我们一般私有化的时变量,并没有对对象进行私有化,但是实际上在C++中这个是可以私有化的,并且我们将该对象称为成员对象。

接下来我们先看看代码效果是什么样子的?

在这里插入图片描述

如上所示,首先会调用Buick构造函数,然后紧接着是BMW构造函数,最后才是Maker构造函数,细心的我们会发现如果类有成员对象,那么先调用成员对象的构造函数,再调用本身的构造函数,析构函数的调用顺序反之。

那么此时我们如果将Buick和BMW的顺序互换一下,代码运行效果会是什么呢?

代码运行结果如下:

在这里插入图片描述
并且还需要注意一点:

如果有成员对象,那么实例化对象时,必须保证成员对象的构造和析构能被调用

初始化列表

实例:

class BMW2
{
public:BMW2(int a){cout << "BMW2有参构造" << a << endl;}~BMW2(){cout << "BMW2析构" << endl;}
};class Buick2
{
public:Buick2(){cout << "Buick2构造" << endl;}~Buick2(){cout << "Buick2析构" << endl;}
};class Maker2
{
public:Maker2() :bmw(10){cout << "Maker2构造" << endl;}~Maker2(){cout << "Maker2析构" << endl;}
private:Buick2 bui;//成员对象BMW2 bmw;//成员对象
};void test02()
{Maker2 m;
}int main()
{test02();
}

对上述代码进行分析:

Maker2() :bmw(10){cout << "Maker2构造" << endl;}

当调用Maker2的构造函数时,会调用成员对象bmw的有参构造函数,并将10赋值给a。

代码运行结果如下:

在这里插入图片描述
那此时有多个对象需要指定调用某个构造函数,我们需要用逗号隔开。

实例如下:

class BMW2
{
public:BMW2(int a){cout << "BMW2有参构造" << a << endl;}~BMW2(){cout << "BMW2析构" << endl;}
};class Buick2
{
public:Buick2(int b, int c){cout << "Buick2构造" << endl;}~Buick2(){cout << "Buick2析构" << endl;}
};class Maker2
{
public:Maker2(int a, int b, int c) :bmw(a), bui(b, c){cout << "Maker2构造" << endl;}~Maker2(){cout << "Maker2析构" << endl;}
private:Buick2 bui;//成员对象BMW2 bmw;//成员对象
};void test02()
{Maker2 m(30, 10, 20);
}int main()
{test02();
}

对上述代码进行分析:

Maker2(int a, int b, int c) :bmw(a), bui(b, c)
{cout << "Maker2构造" << endl;
}

当使用Maker2进行实例化对象为m时,需要使用有参构造函数,将30,10,20这三个值分别传给bmw和bui对象,并且中间用逗号隔开。

代码运行结果如下:

在这里插入图片描述

除了以上几点,还有几点需要我们注意:

  1. 初始化列表是干什么用的,指定调用成员对象的某个构造函数
  2. 初始化列表只能写在构造函数
  3. 如果使用了初始化列表,那么所有的构造函数都要写初始化列表
  4. 可以使用对象的构造函数传递数值给成员对象的变量

结束语

如果觉得这篇文章还不错的话,记得点赞 ,支持下!!!

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

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

相关文章

Linux上编译sqlite3库出现undefined reference to `sqlite3_column_table_name‘

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> 在Ubuntu 18上编译sqlite3库后在运行程序时出现undefined reference to sqlite3_column_table_name’的错误。网上的说法是说缺少SQLITE_ENABLE_COLUMN_M…

libevent

libevent 库概念和特点 开源。精简。跨平台&#xff08;Windows、Linux、maxos、unix&#xff09;。专注于网络通信&#xff08;不一定非用在网络当中&#xff0c;比如下面的读写管道&#xff09;。 libevent特性&#xff1a;基于"事件"&#xff0c;面向“文件描述符…

软件开发项目文档系列之十如何撰写测试用例

目录 1 概述1.1 编写目的1.2 定义1.3 使用范围1.4 参考资料1.5 术语定义 2 测试用例2.1 功能测试2.1.1 用户登录功能2.1.2 商品搜索功能 2.2 性能测试2.2.1 网站响应时间2.2.2 并发用户测试 附件&#xff1a; 测试用例撰写的要素和注意事项附件1 测试用例要素附件2 测试用例的注…

SpringBoot启动流程简介

一、Application启动类中main方法启动 SpringBootApplication(scanBasePackages {"com.springboot.lean"}) public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);} } 1.1 SpringBootApplication注…

Maven中<scope>中等级的区别

标签指定了依赖项的级别吗&#xff0c;默认是compile &#xff08;编译&#xff09;。意味着依赖项将会在编译时和运行时都被包含在项目中 <scope> 标签指定了依赖项的级别为 import 。除了 import 级别&#xff0c;Maven还支持以下几种级别&#xff1a; compile &#x…

【鸿蒙软件开发】ArkUI容器组件之Grid(网格布局)

文章目录 前言一、Grid1.1 子组件GridItem是什么子组件接口属性事件示例代码 1.2 接口参数 1.3 属性1.4 Grid的几种布局模式1.5 GridDirection枚举说明1.6事件ItemDragInfo对象说明 1.7 示例代码 总结 前言 Grid容器组件&#xff1a;网格容器&#xff0c;由“行”和“列”分割…

【flask跨域问题】解决它

大概7-8年前&#xff0c;前后端还没开始分离或者刚开始分离的之前&#xff0c;跨域问题很多。 后来我就没在遇到过了&#xff0c;这次做一个小项目&#xff0c;又遇到了&#xff0c;记录下。 现在前端的脚手架都自己能解决了。 1. 跨域 是因为出于浏览器的同源策略限制。同源…

【数据结构初级(2)】单链表的基本操作和实现

文章目录 Ⅰ 概念及结构1. 单链表的概念2. 单链表的结构 Ⅱ 基本操作实现1. 定义单链表结点2. 创建新结点3. 单链表打印4. 单链表尾插5. 单链表头插6. 单链表尾删7. 单链表头删8. 单链表查找9. 在指定 pos 位置前插入结点10. 删除指定 pos 位置的结点11. 单链表销毁 本章实现的…

轻量封装WebGPU渲染系统示例<18>- 材质多pass实现GPU Compute计算(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/ComputeMaterialTest.ts 系统特性: 1. 用户态与系统态隔离。 细节请见&#xff1a;引擎系统设计思路 - 用户态与系统态隔离-CSDN博客 2. 高频调用与低频调用隔离。…

P02项目(学习)

★ P02项目 项目描述&#xff1a;安全操作项目旨在提高医疗设备的安全性&#xff0c;特别是在医生离开操作屏幕时&#xff0c;以减少非授权人员的误操作风险。为实现这一目标&#xff0c;我们采用多层次的保护措施&#xff0c;包括人脸识别、姿势检测以及二维码识别等技术。这些…

AD9371 官方例程 NO-OS 主函数 headless 梳理(二)

AD9371 系列快速入口 AD9371ZCU102 移植到 ZCU106 &#xff1a; AD9371 官方例程构建及单音信号收发 ad9371_tx_jesd -->util_ad9371_xcvr接口映射&#xff1a; AD9371 官方例程之 tx_jesd 与 xcvr接口映射 AD9371 官方例程 时钟间的关系与生成 &#xff1a; AD9371 官方…

数据结构-邻接表广度优先搜索(C语言版)

对于一个有向图无向图&#xff0c;我们下面介绍第二种遍历方式。 广度优先搜索&#xff0c;即优先对同一层的顶点进行遍历。 如下图所示&#xff1a; 该例子&#xff0c;我们有六个顶点&#xff0c; 十条边。 对于广度优先搜索&#xff0c;我们先搜索a&#xff0c;再搜索abc…

5、Python中的变量和表达式:变量的定义、赋值和数据类型转换

文章目录 Python中的变量和表达式:变量的定义、赋值和数据类型转换变量的定义变量的赋值数据类型转换注意事项表达式总结Python中的变量和表达式:变量的定义、赋值和数据类型转换 Python是一种高级编程语言,以其简洁明了的语法和强大的功能而闻名。在Python编程中,变量和表…

力扣第121题 买卖股票的最佳时机 c++ 动态规划解法 熟练dp思维 之简单题 附Java代码

题目 &#xff08;在我以前有贪心解法&#xff0c;也可以去参考参考&#xff09; 贪心解法 股票问题https://blog.csdn.net/jgk666666/article/details/133978629 121. 买卖股票的最佳时机 简单 相关标签 数组 动态规划 给定一个数组 prices &#xff0c;它的第 i 个元…

Java并发面试题知识点总结(中篇)

大家好&#xff0c;我是栗筝i&#xff0c;从 2022 年 10 月份开始&#xff0c;我便开始致力于对 Java 技术栈进行全面而细致的梳理。这一过程&#xff0c;不仅是对我个人学习历程的回顾和总结&#xff0c;更是希望能够为各位提供一份参考。因此得到了很多读者的正面反馈。 而在…

NVMe FDP会被广泛使用吗?

文章开头&#xff0c;我们需要先了解固态硬盘的读写机制。我们知道&#xff0c;固态硬盘的存储单元是由闪存颗粒组成的&#xff0c;无法实现物理性的数据覆盖&#xff0c;只能擦除然后写入&#xff0c;重复这一过程。因而&#xff0c;我们可以想象得到&#xff0c;在实际读写过…

Mac VsCode g++编译报错:不支持C++11语法解决

编译运行时报错&#xff1a; [Running] cd “/Users/yiran/Documents/vs_projects/c/” && g 1116.cpp -o 1116 && "/Users/yiran/Documents/vs_projects/c/"1116 1116.cpp:28:22: warning: range-based for loop is a C11 extension [-Wc11-extensi…

Maven3.9.1安装及环境变量配置

一、Maven的下载与安装 maven各版本下载地址 打开链接后自行选择对应版本 下载完成后解压安装,最好别选择c盘,安装目录路径等使用英文,避免产生其他问题 我这里选择的是D盘 二、Maven的环境变量配置 2.1、右键点击此电脑选择属性&#xff0c;点击高级系统设置&#xff0c;点…

jenkins结合k8s部署动态slave

1、完成k8s连接 在完成jenkins的部署后现安装kubernets的插件 如果jenkins 是部署在k8s集群中只需要填写一下 如果是非本集群的部署则需要填写证书等 cat ./config echo ‘certificate-authority-data-value’ | base64 -d > ./ca.crt echo ‘client-certificate-data’ |…

结合组件库实现table组件树状数据的增删改

如图所示&#xff0c;可以实现树状数据的新增子项&#xff0c;新增平级&#xff0c;删除。主要用到了递归 代码&#xff1a; <template><el-table :data"tableData" style"width: 100%; margin-bottom: 20px" row-key"id" border def…