c++11的构造函数继承

https://en.cppreference.com/w/cpp/language/using_declaration

在[Inheriting constructors]这一节.

其实叫做"基类的构造函数前置"比较好.

像mystring继承自string类,但仍然是提供字符串功能.new的时候仍旧希望保留旧有的初始化传参方式.这时候在mystring里一一再实现(调用基类)就比较麻烦.

但在c++11之前只能这样.

c++11之前的默认构造方式(淡然c++11之后还是)是,先把各个基类的默认初始化函数调用一遍.然后对派生字段做默认初始化.

c++11之前用户定义的构造函数,可以在初始化列表里调用基类的构造函数,同时可以传参.基类的构造函数仍旧是先调用一遍.

c++11开始,就有了using Base::Base;的写法,当编译器在派生类里找不到相应的构造函数时,就会在这个基类Base里找.在此之后,会调用其它基类的默认构造函数,派生类的字段则是赋值初始化.(这也是c++11之后引入的)

Inheriting constructors

If the using-declaration refers to a constructor of a direct base of the class being defined (e.g. using Base::Base;), all constructors of that base (ignoring member access) are made visible to overload resolution when initializing the derived class.

If overload resolution selects an inherited constructor, it is accessible if it would be accessible when used to construct an object of the corresponding base class: the accessibility of the using-declaration that introduced it is ignored.

If overload resolution selects one of the inherited constructors when initializing an object of such derived class, then the Base subobject from which the constructor was inherited is initialized using the inherited constructor, and all other bases and members of Derived are initialized as if by the defaulted default constructor (default member initializers are used if provided, otherwise default initialization takes place). The entire initialization is treated as a single function call: initialization of the parameters of the inherited constructor is sequenced-before initialization of any base or member of the derived object.

翻译下来大概是:

using Base::Base;的用途:

>派生类初始化时,基类的所有构造函数对overload resolution可见,无视权限修饰符.

>如果基类的某个构造函数被选中,那么先用它初始化那个基类,然后"其它的基类"和"派生字段"被初始化就像使用默认的default 构造函数.(采用提供的default initializers,若用户未提供,则发生默认初始化).

>那个基类的构造函数总是最先被调用.

下面是例子代码:

struct B1 {  B1(int, ...) { } };
struct B2 {  B2(double)   { } };

int get();

struct D1 : B1 {
  using B1::B1;  // inherits B1(int, ...)
  int x;
  int y = get();
};

void test() {
  D1 d(2, 3, 4); // OK: B1 is initialized by calling B1(2, 3, 4),
                 // then d.x is default-initialized (no initialization is performed),
                 // then d.y is initialized by calling get()
  D1 e;          // Error: D1 has no default constructor
}

struct D2 : B2 {
  using B2::B2; // inherits B2(double)
  B1 b;
};

D2 f(1.0);       // error: B1 has no default constructor

As with using-declarations for any other non-static member functions, if an inherited constructor matches the signature of one of the constructors of Derived, it is hidden from lookup by the version found in Derived. If one of the inherited constructors of Base happens to have the signature that matches a copy/move constructor of the Derived, it does not prevent implicit generation of Derived copy/move constructor (which then hides the inherited version, similar to using operator=).

翻译:简单的说,就是using Base:Base之后,派生类可以重载某一个版本来覆盖掉. 基类的copy/move constructor不受这个using的影响,派生类如果没有copy/move constructor,编译器会生成默认的,不会用基类的.

例子代码:

struct B1 {   B1(int); };
struct B2 {   B2(int); };

struct D2 : B1, B2 {
  using B1::B1;
  using B2::B2;
  D2(int);   // OK: D2::D2(int) hides both B1::B1(int) and B2::B2(int)
};
D2 d2(0);    // calls D2::D2(int)

原文地址:https://www.cnblogs.com/xiang-yin/p/12075732.html

时间: 2024-10-30 09:14:23

c++11的构造函数继承的相关文章

C++11中的继承构造函数

时间:2014.06.19 地点:基地 ------------------------------------------------------------------------- 一.问题描述 在继承体系中,如果派生类想要使用基类的构造函数,需要在构造函数中显式声明.如下: struct A { A(int i){} }: struct B:A { B(int i):A(i){} }; 在这里,B派生于A,B 又在构造函数中调用A的构造函数,从而完成构造函数的传递. 又比如如下,当B中存

javascript继承,原型继承,借用构造函数继承,混合继承

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getS

javascript 封装 构造函数继承 非构造函数继承

1 封装 把"属性"(property)和"方法"(method),封装成一个对象,甚至要从原型对象生成一个实例对象 1.1 简单封装:var cat1 = {}; // 创建一个空对象 cat1.name = "大毛"; // 按照原型对象的属性赋值 cat1.color = "黄色"; 1.2 构造函数Prototype模式 Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象.这个对象的

JS继承之借用构造函数继承和组合继承

根据少一点套路,多一点真诚这个原则,继续学习. 借用构造函数继承 在解决原型中包含引用类型值所带来问题的过程中,开发人员开始使用一种叫做借用构造函数(constructor stealing)的技术(有时候也叫做伪造对象或经典继承).这种技术的基本思想相当简单,即在子类型构造函数的内部调用超类型构造函数. 基本模式 function SuperType(){ this.colors = ["red", "blue", "green"]; } fu

C++11 委派构造函数特性怎么使用?

在代码开发中,C语言和C++都是基础语言,是很多web开发人员的入门级必学语言.但在C++98 中,类成员构造问题还存在一些问题,为此C++11提出了一些新特性. C++98中如果一个类有多个构造函数且要实现类成员构造,这些构造函数通常要包含基本相同的类成员构造代码.在最坏的情况下,相同的类成员构造语句被拷贝粘贴在每一个构造函数中. 基于C++98中的类成员构造问题,C++11新特性中,程序员可以将公有的类成员构造代码集中在某一个构造函数里,这个函数被称为目标构造函数.其他构造函数通过调用目标构

C++11委派构造函数的使用方法

在代码开发中,C语言和C++都是基础语言,是很多web开发人员的入门级必学语言.但在C++98 中,类成员构造问题还存在一些问题,为此C++11提出了一些新特性. C++98中如果一个类有多个构造函数且要实现类成员构造,这些构造函数通常要包含基本相同的类成员构造代码.在最坏的情况下,相同的类成员构造语句被拷贝粘贴在每一个构造函数中. 基于C++98中的类成员构造问题,C++11新特性中,程序员可以将公有的类成员构造代码集中在某一个构造函数里,这个函数被称为目标构造函数.其他构造函数通过调用目标构

js继承之借用构造函数继承

一.原型链的缺点 1.1 单纯的原型链继承最大的一个缺点,在于对原型中引用类型值的误修改. 先看一个例子: //父类:人 function Person () { this.head = '脑袋瓜子'; } //子类:学生,继承了"人"这个类 function Student(studentID) { this.studentID = studentID; } Student.prototype = new Person(); var stu1 = new Student(1001);

Javascript继承2:创建即继承----构造函数继承

//声明父类 function SuperClass(id){ //值类型公有属性 this.id = id; //引用类型公有属性 this.books = ['Html','Css']; } //父类声明原型方法 SuperClass.prototype.showBooks = function(){ console.log(this.books) } //声明子类 function ChildClass(id){ //继承父类 SuperClass.call(this,id) } var

构造函数继承--call,apply

构造函数继承的原理 : 通过改变this指向来实现继承(在子类中使用call或apply的方式调用父类  让父类中的this指向子类new出来的对象) 语法格式: function  子类函数名(参数1,参数2){ 父类函数名.call(this,参数1,参数2);     //注: 实例继承 } function  子类函数名(参数1,参数2){ 父类函数名.apply(this,arguments或者[参数1,参数2,参数3,......]);     //注: 实例继承 } call和ap