C++11之继承构造函数(using 声明)

2023-11-14

系列文章

C++11之正则表达式(regex_match、regex_search、regex_replace)

C++11之线程库(Thread、Mutex、atomic、lock_guard、同步)

C++11之智能指针(unique_ptr、shared_ptr、weak_ptr、auto_ptr)浅谈内存管理

C++11之强制类型转换(static_cast,const_cast,dynamic_cast,reinterpret_cast)

C++11之Lanbda表达式(匿名函数)

C++11之右值引用:移动语义和完美转发(带你了解移动构造函数、纯右值、将亡值、右值引用、std::move、forward等新概念)



场景

首先我们来看下面这段代码,有一个Class A、还有一个继承于A的Class B,Class B仅仅增加了一个虚函数,但是就需要把Class A的所有构造方法进行“补齐”。

class A
{
public:
	A(int i){}
	A(double d, int i){}
	A(float f, int i, const char* c){}
};

class B : public A
{
public:
	B(int i):A(i) {}
	B(double d, int i):A(d, i) {}
	B(float f, int i, const char* c):A(f, i, c) {}

	virtual void test(){}
};

继承类的创建释放顺序

就以上面A为父类,B为子类为例,当创建一个B类的对象时,先调用父类的构造函数,然后调用自身的构造函数,在进行释放时,先调用自身的析构函数,然后在调用父类的析构函数。(注: 如果有读者不太了解可以在子类和父类中的构造、析构函数中进行日志输出观察。这块不是重点就一笔带过。)

通过using关键字继承

那么对于上述这个例子中,如果子类B在构造函数中不调用父类A对应的构造函数的话,编译器就会自动调用父类A的默认构造函数,结果A没有默认构造函数就会报错。
在这里插入图片描述
所以为了解决父类中有好多的构造函数,而导致出现这种繁琐的步骤,在C++11中就引入了,子类可以通过using关键字,通过声明继承父类构造函数。

继承成员函数

这里定义了一个父类Base,并有一个参数为double的f函数。又定义了一个子类Derived继承于Base,其中Derived类中有一个参数为intf函数,并且在Derived中使用了using Base::f; 表示在Derived中也可以使用父类的f函数。

class Base
{
public:
	void f(double i)
	{
		cout << "Base:" << i << endl;
	}
};

class Derived : public Base  // 默认为public继承
{
public:
	using Base::f;
	void f(int i)
	{
		cout << "Derived:" << i << endl;
	}
};

int main()
{
	B(1);
	Base b;
	b.f(4.6);
	Derived d;
	d.f(4.9);
	d.f(4);
	return 0;
}

运行结果:

Base:4.6
Base:4.9
Derived:4

这里我们通过using声明,就可以看到子类Derived也可以使用父类的f函数。

继承构造函数

这里对文中最开始的那个代码进行一下改造。

class A
{
public:
	A(int i){}
	A(double d, int i){}
	A(float f, int i, const char* c){}
};

class B : public A
{
public:
	using A::A; // 继承构造函数

	virtual void test() {};
};

在子类B中只需要添加一句using A::A;,就可以继承构造函数。

带有默认参数的构造函数

在父类带有默认参数的构造函数,对于继承构造函数来说,参数的默认值是不会被继承的。但是,默认值会导致父类产生较多个构造函数的版本,并且所有的构造函数均会被子类继承。

class A
{
public:
	A(int a = 3, double = 2.4){}
};

class B : public A
{
public:
	using A::A;
};

以上面这段代码为例,就A(int a = 3, double = 2.4)一个构造函数能产生多少个构造函数版本呢??
A类中会有这些:

  1. A(int =3, double =2.4) 这就是俩个参数的版本
  2. A(int =3)这是只有一个参数的版本
  3. A(const A&)这是拷贝构造函数版本
  4. A() 这是无参构造函数版本

B类中会有这些:

  1. B(int, double) 这就是俩个参数的版本
  2. B(int =3)这是只有一个参数的版本
  3. B(const A&)这是拷贝构造函数版本 (这不是继承的)
  4. B()无参构造函数

所以在父类中有默认构造函数时,需要特别小心多个版本的构造函数的产生。

继承构造函数导致的“冲突”

这种冲突一般在多继承情况下才会存在 ,由于父类中有相同的构造函数导致的子类中有重复定义类型相同的继承构造函数。

class A
{
public:
	A(int a){}
};

class B
{
public:
	B(int b) {}
};

class C : public A, public B
{
public:
	using A::A;
	using B::B;
};

例如上面这个例子,这时我们就可以通过显式定义冲突的构造函数,这样就可以阻止隐式生成的继承构造函数导致的冲突。


class C : public A, public B
{
public:
	using A::A;
	using B::B;
	C(int c); // 显式声明冲突的构造函数
};

继承构造函数的优缺点

优点

通过这种继承构造函数的方式是隐式声明的。也就表示如果这个继承构造函数不使用,那么编译器就不会为其产生真正的函数。通过这个方式生成子类的各种构造函数比原有的方法更加简洁并且高效。

缺点

继承构造函数只能初始化父类中的成员,对于子类中成员变量只能通过C++11的初始化表达式进行设定默认值,具有一定的局限性。

如果父类的构造函数是在private作用域下,或者是子类虚继承父类,这种情况下就不能在子类中生成继承父类的构造函数了。而且子类一旦使用了继承构造函数,那么编译器就不会为子类生成默认的构造函数了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++11之继承构造函数(using 声明) 的相关文章

随机推荐

  • navicat连接oracle进行数据的迁移到mysql以及遇到的问题总结

    打开navicat客户端连接oracle数据服务需要先配置oci dll文件 配置的过程为 打开navicat界面点击 工具 gt 选择 gt OCI 导入oci dll文件 注意 选择instanceclient需要跟oracle数据库的
  • python用bbp公式求圆周率_Python学习笔记

    本文为中国大学MOOC Python语言程序设计 课程学习笔记 课程主讲 嵩天老师 练习平台 Python123 参考教材 Python语言程序设计基础 一 使用公式的方法求解圆周率的值 pi 0 N 1000 for k in range
  • Ubuntu Kylin 20_10 在VMware Workstation Pro上安装

    Ubuntu Kylin 20 10 在VMware Workstation Pro上安装 文章目录 Ubuntu Kylin 20 10 在VMware Workstation Pro上安装 准备工作 在VMVMware Workstat
  • vue-cropper实战使用

    vue cropper 一个优雅的图片裁剪插件 查看演示 Demo README english 更新日志 一 安装使用 1 安装 npm 安装 npm install vue cropper 2 引入 Vue Cropper Vue2 组
  • C++打印类名+函数名的方法

    C 打印类名 函数名的方法 打log的时候经常需要将输出log时所在的类名 函数名写清楚 但是自己敲函数名和类名比较麻烦 复制粘贴的时候也会忘记修改而出错 下面介绍下如何在G GCC编译器下获得函数名和类名 如果只想获得函数名可以用C99的
  • 使用Git-bash将本地项目传到Github

    近几天复习了JavaWeb的一些基础 做了一个简单的管理系统 想放在Github上留个底 但只会用IDEA直接pull 就想着用本地的Gitbash直接pull 花了些时间能好了 现在总结下流程 1 首先在本地目录创建一个文件夹 作为版本库
  • pinia核心模块----store

    目录 一 概念 二 定义store 1 首先store目录下创建user ts文件 主要用来存放与user相关的store 2 页面中使用 一 概念 store简单来说就是数据仓库的意思 我们数据都放在store里面 当然你也可以把它理解为
  • SQL中Group By的使用

    SQL中Group By的使用 1 概述 2 原始表 3 简单Group By 4 Group By 和 Order By 5 Group By中Select指定的字段限制 6 Group By All 7 Group By与聚合函数 8
  • 操作系统(02)- 四个基本特征

    文章目录 一 操作系统的特征 1 并发 2 共享 3 虚拟 4 异步 一 操作系统的特征 操作系统的特征可以分为四类 并发 共享 虚拟 异步 其中并发和共享是最基本的特征 二者互为存在条件 后面会给出详细解释 下面详细的介绍这四种特征 1
  • 中国智能建筑行业运行状况与十四五应用前景调研报告2022版

    中国智能建筑行业运行状况与十四五应用前景调研报告2022版 修订日期 2021年12月 搜索鸿晟信合研究院查看官网更多内容 第一章 智能建筑发展概述 1 1 智能建筑的相关概念 1 1 1 智能建筑的定义 1 1 2 智能建筑的层次划分 1
  • Ubuntu安装redis5.0.0

    一 下载 sudo wget http download redis io releases redis 5 0 0 tar gz 如果慢 可以传上去 二 解压编译安装 解压后 切换目录 cd app redis 5 0 0 编译 make
  • 【C++】对数组指针的理解,例如 int (*p)[3]

    目录 简介 思考 理解 结语 简介 Hello 非常感谢您阅读海轰的文章 倘若文中有错误的地方 欢迎您指出 昵称 海轰 标签 程序猿 C 选手 学生 简介 因C语言结识编程 随后转入计算机专业 获得过国家奖学金 有幸在竞赛中拿过一些国奖 省
  • 【MYSQL】mysql1130错误与安装重置密码

    1 连接服务器 mysql u root p 2 看当前所有数据库 show databases 3 进入mysql数据库 use mysql 4 查看mysql数据库中所有的表 show tables 5 查看user表中的数据 sele
  • freeswitch编译过程以及添加odbc连接mysql

    freeswitch 编译 参考官网wiki bootstrap sh j configure prefix home make make j install make j cd sounds install make j cd moh i
  • Git的Patch功能

    本文整理编辑自 http www cnblogs com y041039 articles 2411600 html http yuxu9710108 blog 163 com blog static 2375153420101114488
  • 可以免费使用的ChatGPT-4,微软开放Bing Chat功能,供用户体验

    微软Bing取消了 Bing Chat的等待名单 现在用户可以通过使用 Edge 浏览器并使用微软帐户登录就可以使用Bing Chat了 入口 打开Bing首页 用户点击 聊天 Chat 即可进入Bing Chat界面 目前Bing Cha
  • Open3D(C++) 模型锐化

    目录 一 模型锐化 1 概述 2 主要函数 二 代码实现 三 结果展示 1 原始模型 2 锐化处理 一 模型锐化 1 概述 Open3D中的实现一种模型锐化处理的算法 该算法的输出值 v o v o v
  • uni.switchTab()跳转不刷新页面问题

    uni switchTab 跳转不刷新页面问题 大家应该都遇到过 调转到 tabBar 里面的页面时 只能使用 uni switchTab 或者是 uni navigator 跳转 使用 uni reLauch 或者是 uni redire
  • 【BLE】-CC2541 OSAL操作系统抽象层应用程序接口API介绍

    参考源source 简介 目的 本文档的目的是定义OS抽象层 OSAL 的API 这个API适用于TI协议栈软件组的产品 例如Z 堆栈 RemoTI 和BLE 适用范围 该文件列举了由OSAL提供的所有函数调用 详细地说明了所有函数调用 方
  • C++11之继承构造函数(using 声明)

    系列文章 C 11之正则表达式 regex match regex search regex replace C 11之线程库 Thread Mutex atomic lock guard 同步 C 11之智能指针 unique ptr s