C++派生类的构造函数

1.构造函数

定义了派生类之后,要使用派生类就需要声明该类的对象。对象在使用之前必须初始化。

派生类的成员对象是由所有基类的成员对象共同组成的。因此构造派生类函数的对象时,就要对基类的成员对象和新增的成员对象进行初始化。

基类的构造函数并没有继承下来,要完成这些工作,就必须给派生类添加新的构造函数。派生类对于基类的很多成员对象是不可以直接访问的,因此要完成对基类成员对象初始化工作,需要通过调用基类的构造函数。

派生类的构造函数需要以合适的初值作为参数,其中一些参数要传递给基类的构造函数,用于初始化相应的成员,另一些参数要用于对派生类新增的成员对象进行初始化。

在构造派生类对象时,会首先调用基类的构造函数,来初始化它们的数据成员,然后按照构造函数初始化列表中指定的方式初始化派生类新增的成员对象,最后才执行派生类构造函数的函数体。

(1)派生类构造函数的一般语法形式
派生类名::派生类名(参数表):基类名1(基类1初始化参数表),...,基类名n(基类n初始化参数表),成员对象名1(成员对象1初始化参数表),...,成员对象名m(成员对象m初始化参数表)
{派生类构造函数的其他初始化操作;
}

这里派生类的构造函数名于派生类名相同。在构造函数的参数表中,需要给出初始化基类数据和新增成员对象所需要的参数。在参数表之后,列出需要使用参数进行初始化的基类名和成员对象名及各自的初始化参数表,各项之间用逗号隔开。
当一个类同时有多个基类时,对于所有需要给予参数进行初始化的基类,都要显式给出基类名和参数表。对于使用默认构造函数的基类,可以不给出类名。同样,对于成员对象,如果是使用默认构造函数,也不需要写出对象名和参数表。

(2)声明派生类构造函数

如果对基类初始化时,需要调用基类的带有形参表的构造函数时,派生类就必须声明构造函数,提供一个将参数传递给基类构造函数的途径,保证基类进行初始化时能获得必要的数据。

如果不需要调用基类的带参数的构造函数,也不需要调用新增的成员对象的带参的构造函数,派生类也可以不用声明构造函数,全部采用默认的构造函数,这时新增成员的初始化工作可以用其他公有成员函数来完成。当派生类没有显式构造函数时,系统会隐含生成一个默认构造函数,该函数会使用基类的默认构造函数对继承自基类的数据初始化,并且调用派生类的类类型的成员对象的默认构造函数,对这些成员对象初始化。

派生类构造函数执行的一般顺序如下:
①调用基类的构造函数,调用顺序按照它们被继承时声明的顺序(从左到右)。
②对派生类新增的成员对象初始化,初始化顺序按照它在类中声明的顺序。
③执行派生类的构造函数体中的内容。

【注意】构造函数初始化列表中基类名、对象名之间的次序无关紧要,它们各自出现的顺序可以是任意的,无论它们的顺序怎样安排,基类构造函数的调用和各个成员对象的初始化顺序都是确定的。

【例】派生类的构造函数举例(多继承,含有内嵌对象),有3个基类B1,B2和B3。其中B3只有一个默认构造函数,其余两个基类的成员只有一个带有参数的构造函数。类D由这三个基类,结果公有继承派生而来。派生类新增了3个私有对象成员,分别是B1,B2和B3类的对象。

#include<iostream>
using namespace std;class B1//基类B1,构造函数有参数
{
public:B1(int i){cout << "构造B1对象" << i << endl;}
};class B2//基类B2,构造函数有参数
{
public:B2(int j){cout << "构造B2对象" << j << endl;}
};class B3//基类B3,构造函数无参数
{
public:B3(){cout << "构造B3对象" << endl;}
};class D:public B2,public B1,public B3//派生类D,注意基类名的顺序
{
public://派生类的公有成员D(int a,int b,int c,int d):B1(a),b2(d),b1(c),B2(b){}//注意类名的个数与顺序,注意成员对象名的个数与顺序private://派生类的私有成员对象B1 b1;B2 b2;B3 b3;
};int main()
{D d(1, 2, 3, 4);return 0;
}

运行结果:
在这里插入图片描述
结果分析:
因为**基类和内嵌对象成员都具有默认构造函数,所以派生类中需要显式声明一个构造函数用来初始化基类及内嵌对象成员。**派生类的构造函数定义为:

D(int a,int b,int c,int d):B1(a),b2(d),b1(c),B2(b){}

构造函数的参数表中给出了基类及内嵌对象成员所需要的全部参数,在冒号之后,分别列出各个基类及内嵌对象名和各自的参数。需要注意两个问题:一是,这里并没有列出全部基类和成员对象,由于B3类只有默认构造函数,不需要给它传递参数,因此,基类B3以及B3类成员对象b3就不必列出。二是,在派生类的构造函数中基类名和成员对象名的顺序是随意的。 这个派生类构造函数的函数体为空,只起到了传递参数和调用基类及内嵌对象构造函数的作用。

程序中主函数中只声明了一个派生类D的对象d,生成对象d时调用了派生类的构造函数。D类派生类构造函数的执行情况,应该是先调用基类的构造函数,然后调用内嵌成员对象的构造函数。基类构造函数的调用顺序是按照派生类定义时的顺序,因此应该是先B2,再B1,最后B3;而内嵌对象的构造函数调用顺序应该是按照成员在类中的声明顺序,应该是先B1,再B2,最后B3。

派生类构造函数的定义中,并没有显式列出基类B3和B3类的对象b3,这时系统就会自动调用该类的默认构造函数。如果一个基类同时声明了默认构造函数和带参数的构造函数,那么在派生类构造函数声明中,既可以显式列出基类名和相应的参数,也可以不列出。

(3)派生类构造函数的特点

①基类和内嵌对象成员都具有非默认构造函数时,派生类中需要显式声明一个构造函数用来初始化基类及内嵌对象成员。

②如果一个基类中只有默认构造函数,那么在派生类的构造函数中不需要列出这个基类和这个基类类型的成员对象,不需要它们传参。系统就会自动调用该类的默认构造函数。

③在派生类的构造函数中基类名和成员对象名的顺序是随意的。

④如果派生类构造函数的函数体为空,那么该派生类的构造函数只起到了传递参数和调用基类及内嵌对象构造函数的作用。

⑤类派生类构造函数的执行情况,应该是先调用基类的构造函数,然后调用内嵌成员对象的构造函数。基类构造函数的调用顺序是按照派生类定义时的顺序,内嵌对象的构造函数调用顺序应该是按照成员在类中的声明顺序。

⑥如果一个基类同时声明了默认构造函数和带参数的构造函数,那么在派生类构造函数声明中,既可以显式列出基类名和相应的参数,也可以不列出。

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

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

相关文章

Linux CentOS系统怎么下载软件

Linux CenOS系统想要下载软件可以在Linux内置的应用商店&#xff0c;并通过Yum 包管理器来下载&#xff08;直接使用yum命令下载软件&#xff09; 在Linux系统中&#xff0c;Yum&#xff08;Yellowdog Updater, Modified&#xff09;是用于管理RPM软件包的一个包管理器。 安装…

ChatGPT-4.0:你准备好了吗?

3202年了&#xff0c;你还在用ChatGPT 3.5吗&#xff1f; 来感受一下ChatGPT 4.0的魅力吧 文末附升级链接 1、颠倒黑白&#xff1f; 2、解读幽默&#xff1f; 3、小镇做题家&#xff1f; 如何白嫖&#xff1f; 最后 1、科技的发展加快了知识更新的速度&#xff0c;唯有终身…

数据库操作系列-Mysql, Postgres常用sql语句总结

文章目录 1.如果我想要写一句sql语句&#xff0c;实现 如果存在则更新&#xff0c;否则就插入新数据&#xff0c;如何解决&#xff1f;MySQL数据库实现方案: ON DUPLICATE KEY UPDATE写法 Postgres数据库实现方案:方案1&#xff1a;方案2&#xff1a;关于更新&#xff1a;如何实…

前端实现打印1 - 使用 iframe 实现 并 分页打印

目录 打印代码对话框预览打印预览 打印代码 <!-- 打印 --> <template><el-dialogtitle"打印":visible.sync"dialogVisible"width"50%"top"7vh"append-to-bodyclose"handleClose"><div ref"print…

大数据与okcc呼叫中心融合的几种方式

在实际的生产实践中&#xff0c;为提高营销效率&#xff0c;避免骚扰大众&#xff0c;很多呼叫中心业务会与大数据平台进行合作&#xff0c;进行精准营销。 买卖数据是非法的&#xff0c;大数据平台方并不会提供直接的数据&#xff0c;一般情况下&#xff0c;提供的数据都是脱…

C#利用自定义特性以及反射,来提大型项目的开发的效率

在大型项目的开发过程中&#xff0c;需要多人协同工作&#xff0c;来加速项目完成进度。 比如一个软件有100个form&#xff0c;分给100个人来写&#xff0c;每个人完成自己的Form.cs的编写之后&#xff0c;要在Mainform调用自己写的Form。 如果按照正常的Form form1 new For…

【数据分析入门】人工智能、数据分析和深度学习是什么关系?如何快速入门 Python Pandas?

目录 一、前言二、数据分析和深度学习的区别三、人工智能四、深度学习五、Pandas六、Pandas数据结构6.1 Series - 序列6.2 DataFrame - 数据框 七、输入、输出7.1 读取/写入CSV7.2 读取/写入Excel7.3 读取和写入 SQL 查询及数据库表 八、调用帮助九、选择(这里可以参考上一篇文…

【动态规划刷题 5】 最小路径和地下城游戏

最小路径和 链接: 64. 最小路径和 给定一个包含非负整数的 m x n 网格 grid &#xff0c;请找出一条从左上角到右下角的路径&#xff0c;使得路径上的数字总和为最小。 说明&#xff1a;每次只能向下或者向右移动一步。 输入&#xff1a;grid [[1,3,1],[1,5,1],[4,2,1]] 输…

Qt--QPlugin插件

写在前面 Qt–动态链接库一文中提到&#xff0c;动态方式加载dll只能加载 extern "C“ 的导出函数&#xff0c;而无法加载类&#xff0c;因此可以使用Qt提供的插件来实现导出类的动态加载。 QPlugin是Qt插件框架的一部分&#xff0c;是一种轻量级的插件系统&#xff0c;…

数据集的介绍及其标注

水到绝境是风景 人到绝境是重生 一、什么是目标检测 目标检测是计算机视觉领域的一个重要任务&#xff0c;旨在识别和定位图像或视频中的多个目标对象。与图像分类只关注图像属于哪个类别不同&#xff0c;目标检测不仅要确定目标所属的类别&#xff0c;还要准确地标记目标在图…

STM32 DHT11

DHT11 DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。 使用单总线通信 该传感器包括一个电容式感湿元件和一个NTC测温元件&#xff0c;并于一个高性能8位单片机相连&#xff08;模数转换&#xff09;。 DHT11引脚说明 开漏模式下没有输出高电平的能…

一、3.外部硬件中断与进入保护模式

外部硬件中断&#xff1a;处理器接两根线NMI传输非屏蔽中断&#xff08;即无法屏蔽的中断&#xff09;和INTR传输可屏蔽中断 IR0到IR7优先级依次降低 处理器中中断标志位起决定作用&#xff0c;IF为0时屏蔽所有INTR引脚来的信号都被屏蔽 BIOS创建中断向量表 实时时钟和CMOS RAM…