C/C++编程:继承构造函数

引入

在传统C++中,如果派生类要使用使用基类的构造函数,通常需要在构造函数中显式声明:

struct A{
public:A(int i) {}
};struct B : A{B (int i) : A(i){}
};

B派生自A,B又在构造函数中调用A的构造函数,从而完成构造函数的传递。但是如果基类中有大量的构造函数时,可能需要这样写:

struct A{A(int i){};A(double d, int i){}A(float f, int i, const char*c){}
};struct B: A{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 ExtraInterface{};
};

上面B继承自A,但是只添加了一个接口ExtraInterface。如果我们想要在构造B时拥有A这样多的构造方法的时候,就必须意义“透传”各个接口,这时候就很不方便了。

我们知道, C++中规定,如果派生类中要使用基类成员函数,可以用using声明来完成,比如:

#include<iostream>
using namespace std;struct Base{void f(double f) {cout <<"Base:" << endl;}
};struct Derived : Base{using Base::f;void f(int i) {cout <<"Derived :" << endl;};
};int main(){Base b;b.f(4.5);Derived  d;d.f(4.5);
}

上面用了using声明,声明派生类Derived 也使用基类版本的f,派生类中实际上有两个f版本的函数。
在这里插入图片描述

同样的,这个想法被扩展到了构造函数上,子类可以通过使用using声明来继承基类的函数:

struct A{A(int i){};A(double d, int i){}A(float f, int i, const char*c){}
};struct B : A{using A::A; //继承构造函数virtual void ExtraInterface{};
};

实际上,C++11标准继承构造函数被设计为跟派生类中的各种类默认构造函数(默认构造、析构、拷贝构造)一样,是隐式声明的。这意味着如果一个继承构造函数不被相关代码实用,编译器不会为其产生真正的函数代码。

有时候,基类构造函数的参数有默认值。对于继承构造函数来讲,参数的默认值是不会被继承的。事实上,默认值会导致基类产生多个构造函数的版本,这些版本都会被派生类继承。看个例子:

struct A{A(int = 3, double = 2.4){}
};struct B :A{using A::A;
};

上面,B可能从A中继承来的候选构造函数有如下一些:

  • A(int = 3, double = 2.4)
  • A(int = 3)
  • A(const A&); // 默认复制构造函数
  • A(); // 默认构造函数

相应的,B中的构造函数将会包括如下一些。

  • B(int, double); // 继承自A
  • B(int); //继承自A
  • B(const B&); // 不是继承的默认复制构造函数
  • B(); // 不是继承的默认构造函数

另外:

  • 如果基类中的构造函数被声明为私有成员函数,或者派生类是从基类中虚继承的,那么就不能在派生类中声明继承构造函数了。
  • 如果一旦使用了继承构造函数,编译器器就不会在为派生类生成默认构造函数了,也就是说类似下面,继承构造函数没有包含一个无参数版本,就不能通过编译:
#include<iostream>
using namespace std;
struct A{A(int){}
};struct B : A{using A::A;
};int main(){B b;  // error:B没有默认构造函数
}

总结

为此C++11利用关键字using引入了继承构造函数的概念(当派生类要使用基类的成员函数时用)。

#include <iostream>class Base{
public:int val1;int val2;Base(){val1 = 1;};Base(int val) : Base(){ // 委托Base()构造函数val2 = val;}
};class Subclass : public  Base{
public:using  Base::Base; // 继承构造
};int main(){Subclass subclass(3);printf("%d, %d", subclass.val1, subclass.val2);return 0;
}

也就是说,派生类可以通过使用using声明从直接基类继承构造函数:

#include <iostream>
using namespace std;class Base
{
public:Base() { cout << "Base()" << endl; }Base(const Base& other) { cout << "Base(Base&)" << endl; }explicit Base(int i) : num(i) { cout << "Base(int)" << endl; }explicit Base(char c) : letter(c) { cout << "Base(char)" << endl; }private:int num;char letter;
};class Derived : Base
{
public:// Inherit all constructors from Baseusing Base::Base;private:// Can't initialize newMember from Base constructors.int newMember{ 0 };
};int main()
{cout << "Derived d1(5) calls: ";Derived d1(5);cout << "Derived d1('c') calls: ";Derived d2('c');cout << "Derived d3 = d2 calls: " ;Derived d3 = d2;cout << "Derived d4 calls: ";Derived d4;
}/* Output:
Derived d1(5) calls: Base(int)
Derived d1('c') calls: Base(char)
Derived d3 = d2 calls: Base(Base&)
Derived d4 calls: Base()*/

一般而言,当派生类未声明新数据成员或构造函数时,最好使用继承构造函数。

如果类型指定基类,则类模板可以从类型参数继承所有构造函数:

template< typename T >
class Derived : T {using T::T;   // declare the constructors from T// ...
};

如果基类的构造函数具有相同签名,则派生类无法从多个基类继承
https://zh.cppreference.com/w/cpp/language/using_declaration

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

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

相关文章

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

系列文章 C11之正则表达式&#xff08;regex_match、regex_search、regex_replace&#xff09; C11之线程库&#xff08;Thread、Mutex、atomic、lock_guard、同步&#xff09; C11之智能指针&#xff08;unique_ptr、shared_ptr、weak_ptr、auto_ptr&#xff09;浅谈内存管…

继承与派生(Part Ⅱ)——派生类的构造函数/析构函数

派生类的构造函数和析构函数 构造函数的主要作用是对数据成员初始化。基类的构造函数是不能继承的&#xff0c;在声明派生类时&#xff0c;派生类并没有把基类的构造函数继承过来&#xff0c;因此&#xff0c;对继承过来的基类成员初始化的工作也要由派生类的构造函数承担。所…

6.12C++:继承基类的构造函数、单继承的构造函数、多继承的构造函数、派生类复制构造函数、派生类的析构函数

1 继承基类的构造函数 class A{ public:A(){}; // A的构造函数 }; class B : public A{ public:using A:A&#xff1b; }2 单继承的构造函数 class A{ public:A(int i){}; }; class B : public A{ public:B(int i, int j): A(i), bb(j); /i传递给A的构造函数&#xff0c;j初始…

JavaScript构造函数继承

首先介绍对象的call()函数和apply()函数&#xff0c;这两个函数的作用相同、用法不同。它们的作用均是指定当前调用函数的this对象是谁。 call()函数&#xff1a;在第一个传递的参数为一个对象&#xff0c;该对象为该函数的this对象&#xff0c;后面依次传递函数的实参。 apply…

c++继承构造函数

【1】为什么需要继承构造函数&#xff1f; 首先&#xff0c;看看如下代码片段&#xff1a; 1 struct A2 { 3 A(int i)4 {} 5 }; 6 7 struct B : A8 { 9 B(int i) : A(i) 10 {} 11 }; 在C中非常常见&#xff1a;B派生于A&#xff0c;B在构造函数中调用A的构造函…

openAI注册/登录 报错汇总

目录 报错类型问题原因及解决**access denied**<br />**提示An error occurred**<br />**Not available**<br />**同一IP地址频繁注册**<br />**cloudflare死循环验证**<br /> 最后 报错类型 access denied You do not have access to chat.op…

【Java面试题】真实的二面面试题(参考答案为纯个人理解)

1. 你掌握前端的哪些知识&#xff1f; vue2element-ui了解一些css,js 2. 那你说一下vue中的路由吧&#xff1f; vue中的路由是用来设定访问路径的,将路径映射到组件页面上 3. 说一下前端vue页面之间传参的方式&#xff1f; 路由查询字符串(我用的) // 路由定义 { path: /a…

yolo

目标检测 导言&#xff1a;目标检测的任务表述 如何从图像中解析出可供计算机理解的信息&#xff0c;是机器视觉的中心问题。深度学习模型由于其强大的表示能力&#xff0c;加之数据量的积累和计算力的进步&#xff0c;成为机器视觉的热点研究方向。 那么&#xff0c;如何理解…

神经网络与深度学习-学习笔记(5)

1.目标检测与YOLO 目标检测问题 目标检测是在给定的图片中精确找到物体所在位置&#xff0c;并标注出物体的类别。物体的尺寸变化范围很大&#xff0c;摆放物体的角度&#xff0c;姿态不定&#xff0c;而且可以出现在图片的任何地方&#xff0c;并且物体还可以是多个类别。 目…

可见光遥感目标检测(一)任务概要介绍

前言 本篇开始对遥感图像的目标检测进行介绍&#xff0c;介绍了其目标前景、数据集以及评价指标。 本教程禁止转载。同时&#xff0c;本教程来自知识星球【CV技术指南】更多技术教程&#xff0c;可加入星球学习。 Transformer、目标检测、语义分割交流群 欢迎关注公众号CV技…

YOLOv5全面解析教程①:网络结构逐行代码解读

撰文 | Fengwen, BBuf 本教程涉及的代码在&#xff1a; https://github.com/Oneflow-Inc/one-yolov5 教程也同样适用于 Ultralytics/YOLOv5&#xff0c;因为 One-YOLOv5 仅仅是换了一个运行时后端而已&#xff0c;计算逻辑和代码相比 Ultralytics/YOLOv5 没有做任何改变&#x…

可见光遥感图像目标检测(三)文字场景检测之Arbitrary

前言 前面介绍了关于可见光遥感图像目标检测任务主要面临的问题&#xff0c;现在对旋转目标的问题进行优化&#xff0c;为了便于大家理解与之前通用目标检测区别&#xff0c;采用Faster-Rcnn网络模型的架构对旋转目标的检测进行改进。 本教程禁止转载。同时&#xff0c;本教程来…

yolov5的简单使用

yolov5是什么 来自chatGPT的描述如下 YOLOv5是一种目标检测算法&#xff0c;它是YOLO系列算法的最新版本&#xff0c;由Joseph Redmon和Alexey Bochkovskiy等人开发。与之前的版本相比&#xff0c;YOLOv5在准确性和速度方面都有所提高。YOLOv5使用一种名为“Bag of Freebies”…

yolov3_spp项目中的各种配置文件读取

目录 1. open 函数 2. cfg文件夹下文档解析 2.1 hyp.yaml 2.2 my_yolov_3.cfg 3. data文件夹下文档解析 3.1 my_data.data 3.2 其它 后缀名 .ymal .txt .json .cfg .data .names .shapes 可以自定义后缀名&#xff1f;&#xff1f; pyhon文件操作大…

目标检测算法——YOLOv5/YOLOv7改进之结合CBAM注意力机制

&#x1f496;&#x1f496;>>>加勒比海带&#xff0c;QQ2479200884<<<&#x1f496;&#x1f496; &#x1f340;&#x1f340;>>>【YOLO魔法搭配&论文投稿咨询】<<<&#x1f340;&#x1f340; ✨✨>>>学习交流 | 温澜潮…

​目标检测算法——YOLOv5/YOLOv7改进之结合Criss-Cross Attention

&#xff08;一&#xff09;前沿介绍 论文题目&#xff1a;CCNet: Criss-Cross Attention for Semantic Segmentation 论文地址&#xff1a;https://arxiv.org/pdf/1811.11721.pdf 代码地址&#xff1a;https://github.com/shanglianlm0525/CvPytorch 本文是ICCV2019的语义分…

目标检测算法——YOLOv5/YOLOv7改进之GSConv+Slim Neck(优化成本)

>>>深度学习Tricks&#xff0c;第一时间送达<<< 目录 &#xff08;一&#xff09;前言 1.GSConv模块 2.Slim Neck&#xff08;GSBottleneckVoVGSCSP&#xff09; &#xff08;二&#xff09;YOLOv5改进之GSConvSlim Neck 1.配置common.py文件 2.配置yo…

目标检测算法——YOLOv5改进|增加小目标检测层

&#x1f496;&#x1f496;>>>加勒比海带&#xff0c;QQ2479200884<<<&#x1f496;&#x1f496; &#x1f340;&#x1f340;>>>【YOLO魔法搭配&论文投稿咨询】<<<&#x1f340;&#x1f340; ✨✨>>>学习交流 | 温澜潮…

【学习笔记】YOLOv5训练自己的数据集

训练自己的数据集进行总结&#xff0c;方便接下来的学习 目录 1.设置文件夹 2.标记自己的数据集 2.1在百度图片上找到自己想要的图片并批量下载 2.2labelimg软件的使用 3.修改配置文件 3.1AOCAO parameter.yaml 3.2AOCAO model.yaml 4.开始训练 4.1改代码 4.2训练过…

Tips and tricks for Neural Networks 深度学习训练神经网络的技巧总结(不定期更新)

文章目录 本文说明Debug 技巧Overfit一个简单的Batch无法复现之前的结果 数据处理平衡数据数据增强&#xff08;Data Augmentation&#xff09;图片增强 使用Embedding数据压缩数据标准化&#xff08;Normalization&#xff09;标签平滑&#xff08;LabelSmoothing&#xff09;…