系列文章

C++11之正则表达式(regex_match、regex_search、regex_replace)

C++11之线程库(Thread、Mutex、atomic、lock_guard、同步)

C++11之智能指针(unique_ptr、shared_ptr、weak_ptr、auto_ptr)浅谈内存管理

C++11之强制类型转换(static_cast,const_cast,dynamic_cast,reinterpret_cast)

C++11之Lanbda表达式(匿名函数)

C++11之右值引用:移动语义和完美转发(带你了解移动构造函数、纯右值、将亡值、右值引用、std::move、forward等新概念)


文章目录

  • 系列文章
  • 场景
    • 继承类的创建释放顺序
  • 通过using关键字继承
    • 继承成员函数
    • 继承构造函数
    • 带有默认参数的构造函数
    • 继承构造函数导致的“冲突”
  • 继承构造函数的优缺点
    • 优点
    • 缺点

场景

首先我们来看下面这段代码,有一个Class A、还有一个继承于A的Class B,Class B仅仅增加了一个虚函数,但是就需要把Class A的所有构造方法进行“补齐”。

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

继承类的创建释放顺序

就以上面A为父类,B为子类为例,当创建一个B类的对象时,先调用父类的构造函数,然后调用自身的构造函数,在进行释放时,先调用自身的析构函数,然后在调用父类的析构函数。(注: 如果有读者不太了解可以在子类和父类中的构造、析构函数中进行日志输出观察。这块不是重点就一笔带过。)

通过using关键字继承

那么对于上述这个例子中,如果子类B在构造函数中不调用父类A对应的构造函数的话,编译器就会自动调用父类A的默认构造函数,结果A没有默认构造函数就会报错。

所以为了解决父类中有好多的构造函数,而导致出现这种繁琐的步骤,在C++11中就引入了,子类可以通过using关键字,通过声明继承父类构造函数。

继承成员函数

这里定义了一个父类Base,并有一个参数为double的f函数。又定义了一个子类Derived继承于Base,其中Derived类中有一个参数为intf函数,并且在Derived中使用了using Base::f; 表示在Derived中也可以使用父类的f函数。

class Base
{public:void f(double i){cout << "Base:" << i << endl;}
};class Derived : public Base  // 默认为public继承
{public:using Base::f;void f(int i){cout << "Derived:" << i << endl;}
};int main()
{B(1);Base b;b.f(4.6);Derived d;d.f(4.9);d.f(4);return 0;
}

运行结果:

Base:4.6
Base:4.9
Derived:4

这里我们通过using声明,就可以看到子类Derived也可以使用父类的f函数。

继承构造函数

这里对文中最开始的那个代码进行一下改造。

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

在子类B中只需要添加一句using A::A;,就可以继承构造函数。

带有默认参数的构造函数

在父类带有默认参数的构造函数,对于继承构造函数来说,参数的默认值是不会被继承的。但是,默认值会导致父类产生较多个构造函数的版本,并且所有的构造函数均会被子类继承。

class A
{public:A(int a = 3, double = 2.4){}
};class B : public A
{public:using A::A;
};

以上面这段代码为例,就A(int a = 3, double = 2.4)一个构造函数能产生多少个构造函数版本呢??
A类中会有这些:

  1. A(int =3, double =2.4) 这就是俩个参数的版本
  2. A(int =3)这是只有一个参数的版本
  3. A(const A&)这是拷贝构造函数版本
  4. A() 这是无参构造函数版本

B类中会有这些:

  1. B(int, double) 这就是俩个参数的版本
  2. B(int =3)这是只有一个参数的版本
  3. B(const A&)这是拷贝构造函数版本 (这不是继承的)
  4. B()无参构造函数

所以在父类中有默认构造函数时,需要特别小心多个版本的构造函数的产生。

继承构造函数导致的“冲突”

这种冲突一般在多继承情况下才会存在 ,由于父类中有相同的构造函数导致的子类中有重复定义类型相同的继承构造函数。

class A
{public:A(int a){}
};class B
{public:B(int b) {}
};class C : public A, public B
{public:using A::A;using B::B;
};

例如上面这个例子,这时我们就可以通过显式定义冲突的构造函数,这样就可以阻止隐式生成的继承构造函数导致的冲突。


class C : public A, public B
{public:using A::A;using B::B;C(int c); // 显式声明冲突的构造函数
};

继承构造函数的优缺点

优点

通过这种继承构造函数的方式是隐式声明的。也就表示如果这个继承构造函数不使用,那么编译器就不会为其产生真正的函数。通过这个方式生成子类的各种构造函数比原有的方法更加简洁并且高效。

缺点

继承构造函数只能初始化父类中的成员,对于子类中成员变量只能通过C++11的初始化表达式进行设定默认值,具有一定的局限性。

如果父类的构造函数是在private作用域下,或者是子类虚继承父类,这种情况下就不能在子类中生成继承父类的构造函数了。而且子类一旦使用了继承构造函数,那么编译器就不会为子类生成默认的构造函数了。

C++11之继承构造函数(using 声明)相关推荐

  1. C++11:继承构造函数

    前言 首先我们来看一种情况,有如下示例: class Base {public:Base(int i):x(i),y(0){}Base(int i,double j):x(i),y(j){}Base( ...

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

    引入 在传统C++中,如果派生类要使用使用基类的构造函数,通常需要在构造函数中显式声明: struct A{public:A(int i) {} };struct B : A{B (int i) : ...

  3. C++11 继承构造函数

    1.简介 子类为完成基类初始化,在 C++11 之前,需要在初始化列表调用基类的构造函数,从而完成构造函数的传递.如果基类拥有多个构造函数,那么子类也需要实现多个与基类构造函数对应的构造函数. cla ...

  4. [C++11]继承构造函数

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

  5. C++进阶教程 - 委托构造函数和继承构造函数

    委托构造函数 什么是委托构造函数? 委托构造函数是由C++11引入的新概念,是对C++构造函数的改进,允许构造函数使用初始化列表调用同类中的其他构造函数,旨在简化构造函数的书写,提升代码的可维护性,降 ...

  6. C++三大继承构造函数的执行顺序详解

    写的挺好的,关于继承和构造函数的先后顺序问题. 转自: http://blog.csdn.net/daheiantian/archive/2011/02/18/6438782.aspx 一.单继承 核 ...

  7. 【 C++11 】列表初始化、声明、范围for、STL中一些变化

    目录 1.C++11简介 2.统一的列表初始化 { }初始化 initializer_list容器 3.声明 auto decltype nullptr 4.范围for 5.STL中一些变化 1.C+ ...

  8. 委托构造函数继承构造函数

    委托构造函数 委托构造函数的引入 小明和李华给外国友人写信从高中写到了考研写累了,突然想唱歌,为了方便这哥俩唱歌,咱写了个唱歌类给他们.这哥俩唱的不好,就限制他俩只能唱三句.因为有1~3句的选择,就写 ...

  9. 无参数的构造函数如何声明对象?

    无参数的构造函数如何声明对象? 下列代码编译时会产生错误的是() 解析1.语句3中Foo b( )是定义一个函数b,参数类型为空,返回值类型为Foo. 所以语句4中b.fun( )会出错,因为b本身不 ...

最新文章

  1. 两帧点云刚性配准的ICP算法
  2. ConcurrentHashMap的源码分析-数据迁移阶段的实现分析
  3. java绘制流程图_如何才能更好地绘制计算机毕业设计中各种图表
  4. Develop系列-API Guides-简介-应用基础
  5. shell中判断远程主机的某个tcp端口是否存活
  6. 高端中餐美食餐饮海报PSD模板,看着就有食欲
  7. Python稳基修炼的经典案例3(计算机二级、初学者必须掌握的例题)
  8. 来自reallh大的游戏编程饕餮大餐!
  9. php中将url中的参数含有%20进行转换或解码
  10. java秒数格式转换_Java中整数(秒数)转换为时分秒格式(xx:xx:xx)
  11. 【系统分析师】考试内容大纲内容
  12. docker 安装redmine,禅道,jira
  13. python基础之列表函数(10)
  14. 传统KTV打入冷宫,全民K歌和唱吧谁是“K歌之王”?
  15. 电子书格式转换方法集锦
  16. 2012年1月51CTO壁纸点评活动获奖名单【已结束】
  17. Qt5 实现文件复制并在指定路径下创建文件夹
  18. OpenCV图片拼接
  19. ESP8266 MP3制作——关于SelectionList从源码中改代码的一次经历
  20. 大数据与认识论一、主体与对象

热门文章

  1. 《C Primer Plus(第6版)中文版》 第5章 运算符、表达式和语句 学习笔记
  2. PHP查找二维数组的内容
  3. Android反射调用goToSleep实现一键锁屏、亮屏
  4. Spring实战(第4版)
  5. 第六届河南省程序设计大赛——B 外星人的供给站
  6. java 编码 类型_java字符类型采用什么编码方式
  7. luliyu-python-day13
  8. OpenFlow 命令
  9. 一入鸿蒙深似海,从此Spring是路人:开篇
  10. Nmap使用教程图文教程(超详细)