C++学习笔记----9、发现继承的技巧(六)---- 有趣且令人迷惑的继承问题(2)

2、给继承类添加虚基类成员函数的重载

        给继承类添加新的虚基类成员函数的重载是可能的。也就是说,可以用新的原型给继承类中的虚成员函数添加重载,但是继续继承基类版本。这个技术使用了using声明来显式包含了继承类中的成员函数的基类定义。下面为示例:

class Base
{
public:virtual void someFunction();
};class Derived : public Base
{
public:using Base::someFunction;    // Explicitly inherits the Base version.virtual void someFunction(int i); // Adds a new overload of someFunction().virtual void someOtherFunction();
};

        注意:在继承类中具有与基类同名但使用不同的参数列表的成员函数是很少见的。

2.1、继承构造函数

        在前面的章节中,可以看到在继承类中使用using声明显式包含了基类的成员函数的定义。对于正常类的成员函数是有效的,对于构造函数也有效,允许从基类继承构造函数。看一下Base与Derived类的如下定义:

class Base
{
public:virtual  ̃Base() = default;Base() = default;explicit Base(int i) {}
};class Derived : public Base
{
public:explicit Derived(int i) : Base(i) {}
};

        Derived构造函数只做了一件事,将它的参数传递给了Base构造函数。

        只用提供的Base构造函数就可以构建一个Base对象,或者是缺省的构造函数,或者是接受int的构造函数。另一方面,可以只用提供的Derived构造函数构建一个Derived对象,要求一个单独的整数作为参数。

        不能使用缺省的Base类的构造函数可构建Derived对象。如下示例:

Base base { 1 };        // OK, calls integer Base ctor.
Derived derived1 { 2 };    // OK, calls integer Derived ctor.
Derived derived2;    // Error, Derived does not have a default ctor.

        由于Derived构造函数只是传递参数给Base构造函数,没有做任何其它事,可以显示使用using声明在Derived类中简单继承Base构造函数如下:

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

        using声明继承了所有的Base的构造函数,所以现在可以用如下的方式构建Derived对象了:

Derived derived1 { 2 };    // OK, calls inherited integer Base ctor.
Derived derived2;        // OK, calls inherited default Base ctor.

        继承类中的继承的构造函数拥有与基类构造函数同样的访问指示符(公共,受保护,或私有)。在基类中使用=delete显式删除的继承构造函数在继承类也会被删除。

2.2、隐藏继承构造函数

        Derived类可以定义与在基类中继承的构造函数同样的参数列表的构造函数。在这种情况下,Derived类的优先级高于继承的构造函数。在下面的例子中,Derived类使用using声明从Base类中继承了所有的构造函数。然而,因为Derived类用单独的float类型的参数定义它自己的构造函数,使用单独的float类型的参数的基类中继承的构造函数就被隐藏了。

class Base
{
public:virtual ~Base() = default;Base() = default;explicit Base(std::string_view str) {}explicit Base(float f) {}
};class Derived : public Base
{
public:using Base::Base;explicit Derived(float f) {}    // Hides inherited float Base ctor
};

        使用这个定义,Derived对象可以生成如下:

	Derived derived1{ "Hello" };   // OK, calls inherited string_view Base ctorDerived derived2{ 1.23f };     // OK, calls float Derived ctorDerived derived3;              // OK, calls inherited default Base ctor.

        使用using声明从基类继承的构造函数的应用有几个限制。

  • 当从基类继承构造函数时,就继承了全部。从基类中只继承部分构造函数是不可能的。
  • 当继承构造函数时,就继承了基类中同样的访问标示,与using声明的访问标示无关。

2.3、继承构造函数与多重继承

        另外一个与继承构造函数相关的限制是多重继承。如果另一个基类有一个同样参数列表的构造函数是不能从其中一个基类继承构造函数的,因为这会带来不确定性。为了解决这个问题,Derived类需要显式定义冲突的构造函数。例如,如下的Derived类尝试继承Based1与Base2的所有构造函数,对于基于float的构造函数就产生了不确定性。

import std;class Base1
{
public:virtual ~Base1() = default;Base1() = default;explicit Base1(float f) {}
};class Base2
{
public:virtual ~Base2() = default;Base2() = default;explicit Base2(std::string_view str) {}explicit Base2(float f) {}
};class Derived : public Base1, public Base2
{
public:using Base1::Base1;using Base2::Base2;explicit Derived(char c) {}explicit Derived(float f) : Base1{ f }, Base2{ f } {}
};int main()
{Derived d{ 1.2f };
}

        在Derived中的第一个using声明继承了Base1的所有构造函数。这意味着Derived获得了如下的构造函数:

Derived(float f);       // Inherited from Base1.

        在Derived中的第二个using声明尝试继承Base2的所有构造函数。然而,这意味着Derived获得了第二个Derived(float)构造函数。该问题可以通过在Derived中显式声明冲突的构造函数,如下:

class Derived : public Base1, public Base2
{
public:using Base1::Base1;using Base2::Base2;explicit Derived(char c) {}explicit Derived(float f) {}
};

        现在Derived类显式声明了一个带有单个float类型的参数的构造函数,解决了不确定性。如果你想,在Derived类中接受float参数的显式声明的构造函数仍然可以在构造函数初始化器中可以传递对Base1与Base2的构造函数的调用,如下:

Derived::Derived(float f) : Base1 { f }, Base2 { f } {}

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

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

相关文章

研发运营一体化(DevOps)能力成熟度模型

目录 应用设计 安全风险管理 技术运 持续交付 敏捷开发管理 基于微服务的端到端持续交付流水线案例 应用设计 安全风险管理 技术运 持续交付

Spring-SpringMVC-SpringBoot理解

Spring是一个完整的框架,能够解决全栈的问题,核心是IOC控制反转和AOP面向切面。 SpringMVC只是Spring的一个模块module,属于Spring框架中WEB层的一部分。 即SpringMVC归属于Spring,不是一个独立的框架 由于SpringMVC配置繁杂使…

关于非中文或者url文本不换行的问题

我在一个写一个简单的url展示的时候,发现url一直溢出不换行,查了各种方法不管用,我请教了我大哥,他直接甩给我两个css放进去就好了 word-break:break-all; 按字符截断换行 /* 支持IE和chrome,FF不支持*/ word-w…

Android 判断手机放置的方向

#1024程序员节|征文# 文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 需求 老板:我有个手持终端,不能让他倒了,当他倒或者倾斜的时候要发出报警; 程序猿:我这..... 老板…

机器学习4

第3章 线性模型 3.1 线性模型的基本形式 3.1.1 线性模型的核心公式 线性模型通过属性的线性组合进行预测,其核心公式为: [ f(x) \omega_1 X_1 \omega_2 X_2 … \omega_d X_d b ] 其中: ω 1 , ω 2 , . . . , ω d \omega_1, \omega_…

医疗实施-项目管理06-估算成本

估算成本 估算成本介绍作用注意事项 常见的估算方法自上而下估算数据分析-储备分析三点估算PERT 常见的估算分类根据产品进行估算根据实施计划估算 估算成本介绍 作用 估算成本是对完成项目所需资源成本进行类似估算的过程。 作用:确定项目所需资金 注意事项 注…

2024-09-28 地址空间与进程控制

一、进程地址空间 Pt.2 同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映射到了不同的物理地址 1. 页表 内存保护与页表标志位 在操作系统中,页表用于管理内存的访问权限。每个页表项通常包含一组标志位&…

SZTU数科导论实验_pandas知识点总结

Pandas nunique示例 value_counts主要功能参数示例输出示例 groupby主要功能常用操作基本语法示例输出示例常用聚合方法 这个函数参数中的as_index选择True或者False有什么影响呢参数 as_indexTrue(默认)参数 as_indexFalse适用场景 info示例代码输出解释…

Spring Boot技术在厨艺交流平台中的创新应用

摘 要 使用旧方法对厨艺交流信息进行系统化管理已经不再让人们信赖了,把现在的网络信息技术运用在厨艺交流信息的管理上面可以解决许多信息管理上面的难题,比如处理数据时间很长,数据存在错误不能及时纠正等问题。 这次开发的厨艺交流平台功能…

二:Python学习笔记--基础知识(1) 变量,关键字,数据类型,赋值运算符,比较运算符

目录 1. 变量 2. python关键字 3. python数据类型 3.1 数字类型 整型 int 浮点型 float 内置函数-type 3.2 字符串类型 3.3 布尔类型 3.4 空类型 3.5 列表类型 3.6 元组类型 3.7 字典类型 4. python赋值运算 5. python比较运算符 1. 变量 组成:必须是数…

基于SSM的BBS社区论坛系统源码

运行环境:ideamysql5.7jdk8maven 使用技术:ssmmysqlshirolayui 功能模块:用户管理、模板管理、帖子管理、公告管理、权限管理等

yolov9目标检测/分割预测报错AttributeError: ‘list‘ object has no attribute ‘device‘常见汇总

这篇文章主要是对yolov9目标检测和目标分割预测测试时的报错,进行解决方案。 在说明解决方案前,严重投诉、吐槽一些博主发的一些文章,压根没用的解决方法,也不知道他们从哪里抄的,误人子弟、浪费时间。 我在解决前&…

Lampiao靶机入侵实战

07-Lampiao靶机入侵实战 一、扫描采集信息 1、获取IP地址 nmap -sn 192.168.81.0/24获得IP地址为:192.168.81.1282、获取端口信息 由于nmap默认情况下只扫描常用的1000个端口,覆盖面并不全,所以建议全端口扫描 nmap -p 1-65535 192.168.…

DiffusionDet: Diffusion Model for Object Detection—扩散模型检测论文解析

DiffusionDet: Diffusion Model for Object Detection—扩散模型检测论文解析 这是一篇发表在CVPR 2023的一篇论文,因为自己本身的研究方向是目标跟踪,之前看了一点使用扩散模型进行多跟踪的论文,里面提到了DiffusionDet因此学习一下。 论文…

读数据工程之道:设计和构建健壮的数据系统21数据获取

1. 数据获取 1.1. 数据获取是将数据从一个地方移动到另一个地方的过程 1.1.1. 数据获取与系统内部获取是不同的 1.2. 数据获取是数据工程生命周期中将数据从源系统移入存储的一个中间步骤 1.3. 数据集成则是将来自不同来源系统的数据组合到一个新的数据集 1.4. 数据获取的…

Java中如何实现对象的序列化与反序列化过程?

1、Java中如何实现对象的序列化与反序列化过程? 在Java中,对象序列化是一个过程,该过程可以将对象的状态(属性)转化为可以传输或者存储的形式,然后再将对象状态(属性)反序列化回对象…

数字后端零基础入门系列 | Innovus零基础LAB学习Day6

今天没有具体的数字IC后端lab实验。今天的重点是熟悉掌握静态时序分析STA中的几类timing path以及setup和hold检查机制(包含setup和hold计算公式)。 芯片流片失败的那些故事 数字后端零基础入门系列 | Innovus零基础LAB学习Day5 等大家把今天内容学习…

QT获取本机所有IP地址以及修改本机IP(注意区分Windows和Linux环境)

QT 获取本机所有 IP 地址 Chapter1 QT 获取本机所有 IP 地址获取本机所有 IP 地址,包括 IPV6的地址,需要引用 QNetworkInterface1.检索所有网络接口:2.获取接口的详细信息:3.获取接口的 IP 地址:4.用于网络诊断和监控&…

KEYSIGHT E4980A是德E4980AL 精密LCR表

Keysight E4980A 精密 LCR 表为各种元件测量提供了精度、速度和多功能性的最佳组合。 E4980A 在低阻抗和高阻抗范围内提供快速测量速度和出色的性能,是元件和材料的一般研发和制造测试的终极工具。 LAN、USB 和 GPIB PC 连接可提高您的设计和测试效率。 Keysight E4…

大语言模型的Scaling Law【Power Low】

NLP-大语言模型学习系列目录 一、注意力机制基础——RNN,Seq2Seq等基础知识 二、注意力机制【Self-Attention,自注意力模型】 三、Transformer图文详解【Attention is all you need】 四、大语言模型的Scaling Law【Power Low】 文章目录 NLP-大语言模型学习系列目录一、什么是…