c++: 继承的详解(理解)

17 篇文章 0 订阅

目录

 

继承的相关概念:

继承权限&访问限定符

赋值兼容规则(public继承)

继承中的作用域:

派生类的默认成员函数:

【面试题】

继承与友元:

继承与static静态成员:

继承体系下派生类的对象模型:


继承的相关概念:

复用:重复性的代码肯定是越少越好,随着组织越来越复杂,单纯在main()中写代码会变的越来越难以维护。而函数则更像是一个小的程序。

          可以从主函数中脱离出来,使我们可以将任务划分的跟更小,大大降低了我们的程序整体复杂性,函数让我们实现了一定程度的代码复用。

继承:继承的机制是面向对象程序设计使代码可以复用的一种手段,它允许程序员在保持原有类特性的基础上继承扩展,增加功能。这样产生的类

          称为派生类!

继承的格式:

继承权限&访问限定符

三种类成员访问限定符:

  1. public公有
  2. protected保护
  3. private私有

三种继承关系

  1. public公有继承
  2. protected保护继承
  3. private私有继承

继承方式及继承权限对应表:

总结:

  1. 基类private成员在派生类中不可访问(如果基类成员不想在类外被直接访问,但需要在派生类中访问就定义为protected,保护成员限定符因继承才出现
  2. public继承是一个接口继承,保持is-a的原则,每个父类可用成员对子类也可用,因为每个子类对象也都是一个父类对象
  3. protected/private是一个实现继承,基类的部分成员并非完全成为子类接口的一部分,是has-a原则
  4. 不管是那种继承方式,派生类内部都可以访问基类的公有和保护成员,私有成员则不可见(编译器语法检测无法通过,所以不能访问)
  5. class默认private,struct默认public
  6. 一般使用public,极少场景才会使用其他

赋值兼容规则(public继承)

  1. 子类对象可以赋值给父类对象(切割或切片:仅把父类含有的对象进行赋值)
  2. 父类对象不能赋值给子类对象
  3. 父类的指针或引用可以指向子类对象
  4. 子类的指针或引用不能指向父类对象(可以通过强制类型转换完成,但是不能调用成员函数,会崩溃)

继承中的作用域:

  1. 在继承体系中基类和派生类都有独立的作用域
  2. 如果在父类和子类中有相同名字的成员;那么在子类中。会将父类的成员隐藏;隐藏以后的直接效果就是:无论在子类的内部或者外部(通过子类成员)访问该成员;全都是访问子类的同名成员(在子类成员中:可以使用基类::基类成员,父类::父类成员访问 访问)--(隐藏或重定义)
  3. 在实际体系中最好不要定义同名成员

 

派生类的默认成员函数:

派生类如果没有显示定义这六个默认成员函数,编译器则会合成

合成:必须依赖与基类,根据基类的相应成员的行为来合成派生类的默认成员函数

生成:不依赖于任何东西,只是编译器根据类的定义简单生成基于基础类型的成员函数

  1. 基类没有缺省构造函数,派生类必须要在初始化类表中显式给出基类名和参数列表
  2. 基类没有定义构造函数,则派生类也可以不用定义,全部使用缺省构造函数
  3. 基类定义了带有形参表构造函数,派生类就一定定义构造函数

【面试题】

系统自动调用析构原因:保证先析构子类在析构父类,栈结构规则

                                     同理:子类初始化时调用父类的默认成员函数初始化父类,调用自己的默认成员函数初始化自己

栈结构:先初始化父类在子类,先析构子类在析构父类

实现一个不能被继承的类:将父类的构造函数定义成私有!

                                       子类合成时先调用父类构造函数,因为私有所有失败!

继承与友元:

友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员(父亲的朋友,不一定是孩子的朋友)

继承与static静态成员:

基类定义了static静态成员,则整个继承体系中只有一个这样的成员,无论派生出多少子类都只有static

继承体系下派生类的对象模型:

                对象模型为对象中非静态成员变量在内存中的布局形式,与成员函数无关

  1. 单继承:一个子类只有一个直接父类
  2. 多继承:一个子类有两个或以上直接父类 
  3.       菱形继承                  我们发现Assistant类中存在两份Person对象,因此在访问继承于基类的成
    员变量时,会存在数据冗余及二义性的问题                                                                                                                                二义性:两边都有(选择困难) 解决方式:1》指定访问那个父类2》虚继承
  4. 虚拟继承——  解决菱形继承的二义性和数据冗余的问题

虚拟继承在进程权限前面加上virtual关键字即可构成虚拟继承

特点:在任何派生类中的virtual基类总共用同一个(共享)对象表示

【注意】:尽量不要设计菱形继承的类
虚继承和直接继承有什么区别
1.时间:在通过继承类对象访问虚基类对象中的成员(包括数据成员和函数成员)时,都必须通过某种间接引用来
完成,这样会增加引用寻址时间(就和虚函数一样),其实就是调整this指针以指向虚基类对象,只不过这个调整
是运行时间接完成的。
2.空间:由于共享所以不必要在对象内存中保存多份虚基类子对象的拷贝,这样较之 多继承节省空间。虚拟继承与
普通继承不同的是,虚拟继承可以防止出现菱形继承时,一个派生类中同时出现了两个基类的子对象。也就是说,
为了保证 这一点,在虚拟继承情况下,基类子对象的布局是不同于普通继承的。因此,它需要多出一个指向基类子
对象的指针

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值