C++11继承构造函数在类中的使用

继承构造函数

  • 概念
  • 衍生问题
  • 使用示例
  • 注意
  • 扩展使用(函数)
    • 示例代码
    • 输出结果
    • 注意

概念

继承构造函数在C++11特性中随之提及,其大概可以理解为:
解决了派生类无法直接使用基类中的构造函数的这一问题
正常情况下,基类定义了自己的构造函数,派生类公有继承基类后,由于派生类隐藏了基类的同名函数,是无法直接使用基类的同名函数的(这里针对于普通函数)。如下所示的例子:
基类Base的定义

class Base
{
public:Base(int a):m_a(a) {}Base(int a, double b):m_a(a),m_b(b) {}Base(int a, double b, string c) :m_a(a), m_b(b), m_c(c) {}
private:int m_a;double m_b;string m_c;
};

派生类Derived

class Derived :public Base 
{
public:private:};

上述的派生类Derived 中没有定义自己的构造函数,虽然是公有继承的基类Base,但是不能直接使用基类的构造函数构造自己的对象。像下面这样是错误的,无法编译通过:
在主函数中的使用:

int main()
{Derived d(12,4.56,"");//编译报错,没有相应的构造函数
}

衍生问题

上述也引发一个问题,若是像下面这样写,也是不正确的。

int main()
{Derived d;//编译报错,尝试引用已删除的函数
}

Derived 类中没有写任何函数,直接使用派生类默认的构造函数。按理这里应该是会调用自己的默认构造函数,但编译报错:尝试引用已删除的函数。这是因为派生类继承基类之后,会将派生类默认生成的构造函数删除吗?求解!!!
原因:Derived 类创建对象d时,先调用基类构造函数,再调用派生类构造函数,基类中已经显式的定义了三个有参构造函数,系统会将默认的无参构造函数删除,所以创建Derived 对象d的时候,调用基类构造函数,没有找到匹配的无参构造函数,已经被系统删除了。
但是改为下面这样:

int main()
{Derived d();//编译通过,但有警告:未调用原型函数(是否是有意用变量定义的?)
}

这是为什么呢????
原因:单独将Derived d();当作一个函数的声明。
同样如果是一个没有继承关系的类,可以这样创建类对象:

class Base
{
public:
private:
};int main()
{Base d();//编译通过,这里也可以这样写 Base d;同样也会编译通过
}

创建对象时,调用的默认的无参构造函数。编译器会为没有显示创建构造函数,析构函数,拷贝构造函数(复制构造函数)以及赋值构造函数(赋值运算符重载)的类自动生成这些函数。

使用示例

下面是继承构造函数的使用。也就是派生类可以调用基类的构造函数的来创建自己的对象的方式。
依旧是最初的例子:

class Base
{
public:Base(int a):m_a(a) {}Base(int a, double b):m_a(a),m_b(b) {}Base(int a, double b, string c) :m_a(a), m_b(b), m_c(c) {}
private:int m_a;double m_b;string m_c;
};class Derived :public Base 
{
public:using Base::Base;//使用基类的构造函数
private:};
int main()
{//使用基类的构造函数Derived d(12,4.56,"");Derived e(2);Derived f(4,5.67);
}

此例中派生类可以使用基类的构造函数来创建对象。方法是在派生类中采用using 声明的方式。
像该例中的using Base::Base;使用时就是:
using 类名::函数名;

注意

以上继承构造函数在使用时,若是派生类中定义了自己的成员变量,继承构造函数不会去初始化派生类定义的成员变量。且上述using 类名::函数名; 调用基类构造函数的方法也适用于函数。

扩展使用(函数)

上面提到这种using声明的方式也可以在函数上使用,下面便是一个示例。

示例代码

依旧采用文章中提到的示例代码稍作修改。

#include <iostream>
#include <string>
using namespace std;class Base
{
public:Base(int a):m_a(a) {}Base(int a, double b):m_a(a),m_b(b) {}Base(int a, double b, string c) :m_a(a), m_b(b), m_c(c) {}void Fun() { cout << "Base::Fun()" << endl; }private:int m_a;double m_b;string m_c;
};class Derived :public Base 
{
public:using Base::Base;//使用基类的构造函数void Fun(int a) { cout << "Derived::Fun()" << endl; }//隐藏
private:};int main()
{//使用基类的构造函数Derived d(12,4.56,"");Derived e(2);Derived f(4,5.67);//使用基类的函数d.Fun();
}

可以看到在使用继承构造函数的基础上,在基类和派生类中新增了函数Fun,两个函数分别位于基类与派生类中,函数名相同,参数不同,此为隐藏关系。更多关于隐藏的介绍可以查看我之前的博文,搜索关键字——隐藏
这里通过d.Fun()调用父类的函数Fun(),但是整个代码是无法通过编译的,要想通过派生类对象调用父类的同名函数需要使用相应的using 类名::函数名来声明
下面稍作修改,是正确的代码:

#include <iostream>
#include <string>
using namespace std;class Base
{
public:Base(int a):m_a(a) {}Base(int a, double b):m_a(a),m_b(b) {}Base(int a, double b, string c) :m_a(a), m_b(b), m_c(c) {}void Fun() { cout << "Base::Fun()" << endl; }private:int m_a;double m_b;string m_c;
};class Derived :public Base 
{
public:using Base::Base;//使用基类的构造函数using Base::Fun;//使用基类的同名函数void Fun(int a) { cout << "Derived::Fun()" << endl; }//隐藏
private:};int main()
{//使用基类的构造函数Derived d(12,4.56,"");Derived e(2);Derived f(4,5.67);//使用基类的函数d.Fun();d.Base::Fun();//与上一行写法都可以,有两种调用方式e.Fun(2);//使用派生类自己的函数
}

上述代码可以编译通过。

输出结果

输出结果为:
在这里插入图片描述

注意

在派生类中引入using声明之后,d.Fun();与d.Base::Fun();都可以达到调用基类的Fun()函数的作用。
在没有引入using声明时,可以采用d.Base::Fun();这种调用方式。d.Base::Fun();的调用已经指明了调用的是基类中的函数。
下面是不引入using声明的基类同名函数Fun()调用示例:

#include <iostream>
#include <string>
using namespace std;class Base
{
public:Base(int a):m_a(a) {}Base(int a, double b):m_a(a),m_b(b) {}Base(int a, double b, string c) :m_a(a), m_b(b), m_c(c) {}void Fun() { cout << "Base::Fun()" << endl; }private:int m_a;double m_b;string m_c;
};class Derived :public Base 
{
public:using Base::Base;//使用基类的构造函数void Fun(int a) { cout << "Derived::Fun()" << endl; }//隐藏
private:};int main()
{//使用基类的构造函数Derived d(12,4.56,"");Derived e(2);Derived f(4,5.67);//使用基类的函数d.Base::Fun();//编译正确
}

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

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

相关文章

grep从文件末尾开始找_新人自学前端到什么程度才能找工作?

这个问题打我记事起到现在&#xff0c;问过我的人&#xff0c;没有1000也有800了。足以见得这个问题是多么的不得人心。自学前端开发&#xff0c;不管他在网上百度了多少资料&#xff0c;看了多少教程&#xff0c;你总得先做个网页出来。所以&#xff0c;很多人都是从html标签开…

Spring Tool Suite 4安装Lombok

Lombok官网&#xff1a;https://www.projectlombok.org/download 文章目录一、下载jar包二、lombok.jar复制三、运行lombok.jar四、安装lombok4.1 点击确定4.2 找到SpringToolSuite4.exe五、以管理员运行Spring Tool Suite 4六、引入lombok依赖6.1 maven项目6.2 普通web项目七、…

base昆明,腾讯云在合作伙伴的阵营中@了TA

戳蓝字“CSDN云计算”关注我们哦&#xff01;技术头条&#xff1a;干货、简洁、多维全面。更多云计算精华知识尽在眼前&#xff0c;get要点、solve难题&#xff0c;统统不在话下&#xff01;在今年的腾讯“三合一”大会上&#xff0c;阿晶得到了这样一则数据&#xff1a;截至目…

IntelliJ IDEA 2019 安装lombok

文章目录一、安装插件二、添加lombok依赖三、重启IntelliJ IDEA四、效果图五、如果不生效一、安装插件 二、添加lombok依赖 <!--Lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version&g…

记录C++类中的一次函数调用

引用 之前遇到一次函数调用结果的问题&#xff0c;今天在这里做一下记录。 一个基类&#xff0c;一个派生类&#xff0c;两个类中都有一个函数名相同&#xff0c;参数相同&#xff0c;参数不同的函数&#xff0c;创建基类指针指向派生类对象&#xff0c;调用相应的函数&#x…

bootstrap table移动端_bootstrap介绍

简介bootstrap是一款前端开发自适应页面的js库&#xff0c;可以让你在开发网页的时候轻松实现网站的PC与移动端兼容&#xff0c;避免在移动端上面出现样式错位等。原理bootstrap的原理是媒体查询CSS3的media&#xff0c;用于检测屏幕&#xff0c;从而改变样式的百分比。结构boo…

Spring Tool Suite 4 自动提示功能

文章目录一、java文件 自动提示二、JavaScript文件 自动提示三、HTML文件 自动提示四、导出配置文件五、编辑导出的配置文件5.1 java提示规则替换5.2 html提示规则替换六、导入配置好的文件一、java文件 自动提示 打开STS→Windows→Preferences→Java→Editor→Content Assis…

关于C++编程中引入头文件的顺序

头文件顺序场景头文件顺序场景 此文仅记录在编写程序的时候&#xff0c;.h或者.cpp引入头文件时&#xff0c;标准库头文件&#xff0c;自己定义的类的头文件的先后顺序。c兼容c语言&#xff0c;故而有时还是涉及到c语言的标准库头文件的引入。这里只记录其引入的顺序。 头文件…

中立安全、赋能产业,UCloud优刻得凭差异化路线进军产业互联

2019年5月28日&#xff0c; 国内领先的中立云计算服务商UCloud优刻得&#xff08;以下简称UCloud&#xff09;在北京召开以“中立安全、赋能产业”为主题的UCloud用户大会暨Think in Cloud北京大会。面对走向纵深的产业互联网&#xff0c;UCloud强调做“不和用户竞争的云”&…

Spring Tool Suite 4 添加反编译插件

文章目录一、进入商店市场二、查找插件&#xff0c;输入jad搜索三、点击安装四、接收协议、安装五、重启Spring Tool Suite 4六、效果图一、进入商店市场 二、查找插件&#xff0c;输入jad搜索 三、点击安装 四、接收协议、安装 五、重启Spring Tool Suite 4 六、效果图

python海龟代码大全_海龟交易系统的Python完全版 | RiceQuant米筐量化社区 交易策略论坛...

zhaoyang-chen 海龟的Python版出炉。为方便对比&#xff0c;这里把java、python两种语言代码同时贴出&#xff0c;回测时间及初始资金均使用页面默认的20140104-20150104&#xff0c;100000.0软妹币。turtle_javapublic class TurtleOriginalStrategy implements IHStrategy {C…

C++中list的一些内置函数

引言 这里记录一些list常用的内置函数&#xff0c;方便日后查看。 内置函数 Lst1.assign() 给list赋值 Lst1.back() 返回最后一个元素 Lst1.begin() 返回指向第一个元素的迭代器 Lst1.clear() 删除所有元素 Lst1.empty() 如果list是空的则返回true Lst1.end() 返回末尾的迭代…

Hadoop精华问答 | NameNode是什么?

戳蓝字“CSDN云计算”关注我们哦&#xff01;2006年项目成立的一开始,“Hadoop”这个单词只代表了两个组件——HDFS和MapReduce。到现在的13个年头,这个单词代表的是“核心”&#xff0c;今天我们就来看看关于Hadoop的精华问答。1Q&#xff1a;NameNode是什么&#xff1f;A&…

01_SpringCoud 整合SpringCoud alibaba Nacos

SpringCoud 核心 整合SpringCoud alibaba Nacos 文章目录一、快速构建一个SpringBoot项目二、添加依赖2.1 SpringMVC2.2 nacos客户端2.3 lombok(可以省略)2.4 actuator监控(图形化)2.5 SpringCloud和spring-cloud-alibaba三、添加注解(无)四、写配置信息五、下载和运行nacos5.1…

python怎么读写_python怎么读写文件

python怎么读写文件&#xff1f;读取操作# 一次性读取整个文件内容with open(致橡树.txt, r, encodingutf-8) as f:print(f.read())# 通过for-in循环逐行读取with open(致橡树.txt, moder) as f:for line in f:print(line, end)time.sleep(0.5)print()# 读取文件按行读取到列表…

C++线程处理函数的返回值

引言 关于线程处理函数&#xff0c;常见的可能是返回值为void类型&#xff0c;那线程处理函数是否能定义自己想要的返回值类型呢&#xff0c;这里请看下面的说明。 C线程返回值 应用环境1、传统的方式获取线程返回值2、使用C Promise和future方式3、promise和future介绍 应…

华为在欧注册HUAWEI ARK OS商标或为海外版操作系统命名;联通电信正探索合并?汽车共享品牌car2go近宣布退出中国……...

关注并标星星CSDN云计算极客头条&#xff1a;速递、最新、绝对有料。这里有企业新动、这里有业界要闻&#xff0c;打起十二分精神&#xff0c;紧跟fashion你可以的&#xff01;每周三次&#xff0c;打卡即read更快、更全了解泛云圈精彩newsgo go go 一加 7 Pro &#xff…

04_SpringCloud 整合Ribbon细粒度配置自定义

SpringCloud 整合Ribbon细粒度配置自定义 文章目录Ribbon内置负载均衡规则&#xff0c;细粒度配置自定义1. 需求分析2. java代码配置2.1. 创建一个类2.2. 然后创建一个类3. 配置文件配置Ribbon内置负载均衡规则&#xff0c;细粒度配置自定义 默认的ZoneAvoidanceRule在没有Zon…

ip访问次数统计 nginx_PHP实现IP访问限制及提交次数的方法详解

一、原理提交次数是肯定要往数据库里写次数这个数据的&#xff0c;比如用户登陆&#xff0c;当用户出错时就忘数据库写入出错次数1&#xff0c;并且出错时间&#xff0c;再出错写2&#xff0c;当满比如5次时提示不允许再登陆&#xff0c;请明天再试&#xff0c;然后用DateDiff计…

C++容器deque的用法

目录 1.deque容器概念 2.deque对象的构造 2.1deque对象的默认构造 2.2deque对象的带参数构造 3.deque头部和末尾的添加移除操作 4.deque的数据存取 5.deque与迭代器 6.deque的赋值 7.deque的大小 8.deque的插入 9.deque的删除 1.deque容器概念 deque容器概念 deque是…