当前位置: 首页 > news >正文

c++11新特性篇-委托构造函数和继承构造函数

C++11引入了委托构造函数(Delegating Constructor)和C++11及后续标准引入了继承构造函数(Inheriting Constructor)两个特性。

1.委托构造函数

委托构造函数是C++11引入的一个特性,它允许一个构造函数调用同一类的另一个构造函数,从而避免在类内部出现相似的初始化代码,提高代码的可维护性。在构造函数的初始化列表中使用 : 符号,可以调用同一类中的其他构造函数

下面是一个简单的例子,展示了如何使用委托构造函数:

#include <iostream>
using namespace std;class Myclass {
public:// 有参构造Myclass(int x, int y):m_X(x), m_Y(y) {}// 无参构造调用有参构造Myclass(): m_X(0), m_Y(10) {}public:int m_X;int m_Y;
};void test01() {// 利用无参构造创建对象// 两个属性值会直接初始化为0和10Myclass mc;cout << mc.m_X << endl; // 0cout << mc.m_Y << endl; // 10}int main() {test01();return 0;
}

在上述例子中,有参构造函数负责实际的初始化工作,而无参构造函数则使用了委托构造函数的方式,通过调用有参构造函数来完成初始化。这样,无参构造函数就避免了代码的重复,并且仍然能够正确地初始化对象。

需要注意的是,委托构造函数的调用必须出现在构造函数的初始化列表中在构造函数主体中调用其他构造函数是不允许的。

使用委托构造函数可以使得类的构造函数更加灵活,能够复用已有的构造函数,减少代码冗余。

2.继承构造函数

C++11中提供的继承构造函数可以让派生类直接使用基类的构造函数,而无需自己再写构造函数,尤其是在基类有很多构造函数的情况下,可以极大地简化派生类构造函数的编写。先来看没有继承构造函数之前的处理方式:

#include <iostream>
#include <string>
using namespace std;class Base
{
public:Base(int i) :m_i(i) {}Base(int i, double j) :m_i(i), m_j(j) {}Base(int i, double j, string k) :m_i(i), m_j(j), m_k(k) {}int m_i;double m_j;string m_k;
};class Child : public Base
{
public:Child(int i) :Base(i) {}Child(int i, double j) :Base(i, j) {}Child(int i, double j, string k) :Base(i, j, k) {}
};int main()
{Child c(520, 13.14, "i love you");cout << "int: " << c.m_i << ", double: " << c.m_j << ", string: " << c.m_k << endl;return 0;
}

通过测试代码可以看出,在子类中初始化从基类继承的类成员,需要在子类中重新定义和基类一致的构造函数,这是非常繁琐的,C++11中通过添加继承构造函数这个新特性完美的解决了这个问题,使得代码更加精简。

继承构造函数的使用方法是这样的:通过使用using 类名::构造函数名(其实类名和构造函数名是一样的)来声明使用基类的构造函数,这样子类中就可以不定义相同的构造函数了,直接使用基类的构造函数来构造派生类对象。

#include <iostream>
#include <string>
using namespace std;class Base
{
public:Base(int i) :m_i(i) {}Base(int i, double j) :m_i(i), m_j(j) {}Base(int i, double j, string k) :m_i(i), m_j(j), m_k(k) {}int m_i;double m_j;string m_k;
};class Child : public Base
{
public:using Base::Base;
};int main()
{Child c1(520, 13.14);cout << "int: " << c1.m_i << ", double: " << c1.m_j << endl;Child c2(520, 13.14, "i love you");cout << "int: " << c2.m_i << ", double: " << c2.m_j << ", string: " << c2.m_k << endl;return 0;
}

在修改之后的子类中,没有添加任何构造函数,而是添加了using Base::Base;这样就可以在子类中直接继承父类的所有的构造函数,通过他们去构造子类对象了

另外如果在子类中隐藏了父类中的同名函数,也可以通过using的方式在子类中使用基类中的这些父类函数:

#include <iostream>
#include <string>
using namespace std;class Base
{
public:Base(int i) :m_i(i) {}Base(int i, double j) :m_i(i), m_j(j) {}Base(int i, double j, string k) :m_i(i), m_j(j), m_k(k) {}void func(int i){cout << "base class: i = " << i << endl;}void func(int i, string str){cout << "base class: i = " << i << ", str = " << str << endl;}int m_i;double m_j;string m_k;
};class Child : public Base
{
public:using Base::Base;using Base::func;void func(){cout << "child class: i'am luffy!!!" << endl;}
};int main()
{Child c(250);c.func();c.func(19);c.func(19, "luffy");return 0;
}

上述示例代码输出的结果为:

child class: i'am luffy!!!
base class: i = 19
base class: i = 19, str = luffy

子类中的func()函数隐藏了基类中的两个func()因此默认情况下通过子类对象只能调用无参的func(),在上面的子类代码中添加了using Base::func;之后,就可以通过子类对象直接调用父类中被隐藏的带参func()函数了。

需要注意的是,using 关键字引入的基类函数在派生类中并不变成虚函数。如果你需要达到虚函数的效果,可以在基类中将相应的函数声明为虚函数。

相关文章:

  • lable与input连用特殊动作效果
  • iPhone通话记录怎么查询?记住这3个简单方法!
  • Vue工程化
  • Python 3.6.10 中的 requests 库 TLS 1.2 强制使用问题及解决方案
  • 利用自动化和条形码优化SAP制造供应链
  • 土木非科班转码测开,斩获10家大厂offer
  • Docker Compose详细教程(从入门到放弃)
  • 使用 Redis 构建轻量的向量数据库应用:图片搜索引擎(一)
  • 携带二进制文件的软件恢复方法
  • 基于SSM+Vue的网上购物商城
  • 编程的简单实例,编程零基础入门教程,中文编程开发语言工具下载
  • Niushop单商户及多商户v5商城系统第三方商业插件cps联盟视频购物及多包装库存转换的安装
  • 后端接口性能优化分析-数据库优化
  • cookie、localStorage 和SessionStorage的区别和特点?
  • 【QT HTTP】使用QtNetwork模块制作基于HTTP请求的C/S架构
  • 「面试题」如何实现一个圣杯布局?
  • 【347天】每日项目总结系列085(2018.01.18)
  • bearychat的java client
  • canvas 绘制双线技巧
  • JS 面试题总结
  • k个最大的数及变种小结
  • ng6--错误信息小结(持续更新)
  • Python中eval与exec的使用及区别
  • SpringBoot 实战 (三) | 配置文件详解
  • 安卓应用性能调试和优化经验分享
  • 包装类对象
  • 对象引论
  • 实战|智能家居行业移动应用性能分析
  • 使用Maven插件构建SpringBoot项目,生成Docker镜像push到DockerHub上
  • 思维导图—你不知道的JavaScript中卷
  • 跳前端坑前,先看看这个!!
  • 我的业余项目总结
  • 在Docker Swarm上部署Apache Storm:第1部分
  • 最简单的无缝轮播
  • Nginx惊现漏洞 百万网站面临“拖库”风险
  • ​2020 年大前端技术趋势解读
  • # Panda3d 碰撞检测系统介绍
  • ###C语言程序设计-----C语言学习(3)#
  • #NOIP 2014# day.2 T2 寻找道路
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • (13)Hive调优——动态分区导致的小文件问题
  • (3)nginx 配置(nginx.conf)
  • (Forward) Music Player: From UI Proposal to Code
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (ros//EnvironmentVariables)ros环境变量
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (深度全面解析)ChatGPT的重大更新给创业者带来了哪些红利机会
  • (转)Sublime Text3配置Lua运行环境
  • (转)菜鸟学数据库(三)——存储过程
  • (转)机器学习的数学基础(1)--Dirichlet分布
  • .NET Core 2.1路线图