一、什么是继承

1、当遇到问题时,先查看现有的类能够解决一部分问题,如果有则继承该类,在此类的基础上进行扩展来解决问题,以此可以缩短解决问题的时间(代码复用)
2、当遇到一个大而复杂的问题时,可以先把复杂的问题拆分成若干个小问题,然后为每个小问题设计一个类进行解决,最后通过继承的方式把这些类汇总到一个类中,从而解决最终的大问题的,以此降低问题的难度,也可以同时让多个程序员一起工作解决问题子类继承父类    派生类继承基类

二、继承的语法

1、继承表
class Son : 继承表[继承方式 父类名1,继承方式 父类名2...]
{成员变量;
public: // 访问控制权限成员函数;
};2、继承方式publicprotectedprivate

三、C++继承的特点:

1、C++中的继承可以有多个父类
2、子类会继承父类的所有内容
3、子类对象可以向它的父类类型转换(使用父类类型指针或引用指向子类对象)(可以缩小),但是父类对象不能向它的子类类型转换(不能使用子类类型指针或引用指向父类对象)(不能扩大)Base* b = new Son;      trueBase& b = son;          trueSon* son = new Base;    falseSon& son = base;        false
4、子类会隐藏父类的同名成员,在子类中直接使用同名成员时,默认使用的是自己的同名成员但是可以通过 父类名::同名成员 的方式指定访问父类的同名成员
5、子类与父类的同名函数是无法构成重载的,因为不在同一个作用域下,并且子类会隐藏同名的父类成员函数,因此只能通过域限定符的方式访问父类的同名成员函数
6、在执行子类的构造函数时,会按照继承表中的顺序执行父类的构造函数,默认执行的是父类的无参构造,可以在子类的构造函数的初始化列表中显示地调用父类的有参构造,最后才执行子类的构造函数Son(int num):Base(参数){}   //  调用Base的有参构造
7、在子类的析构函数执行结束后,才会调用父类的析构函数,会按照继承表顺序,逆序执行父类的析构函数
8、当子类执行拷贝构造时,默认也会调用父类的无参构造,但这是有问题的,因此需要在子类的拷贝构造函数的初始化列表中显示地调用父类的拷贝构造函数Son(Son& that):Base(that) {} // 调用Base的拷贝构造
9、当子类执行赋值操作时,默认不会调用父类的赋值操作函数,如果需要调用父类的赋值操作函数时,可以通过域限定符和赋值函数名的方式调用void Son::operator=(Son& that){父类名::operator=(that);    //调用父类的赋值函数}

四、继承方式和访问控制属性

访问控制属性成员的访问范围:public:        可以在任意位置访问protected:     只能在类内和子类中访问private:       只能在类内访问
继承方式的影响:
1、父类的成员是否能在子类中访问,是在设计父类时的访问控制属性决定的,不受继承方式的影响
2、但是继承方式能够决定父类成员被子类继承后,在子类中变成什么样的访问控制属性,具体情况见表
3、只有使用public继承父类,父类的指针或引用才能指向子类对象 (多态的基础)

五、多重继承和钻石继承

1、多重继承当一个类继承了多个父类时,称为多重继承,会按照继承表的顺序在子类中排列父类的内容,当把子类指针对象转换为父类指针时,编译器会自动计算出该父类内容所在的位置,并让指针偏移到该位置,因此,可能会出现转换后的父类指针与转换前子类指针不相同的情况
2、钻石继承假如有一个类A,类B和类C都继承了类A,类D又同时继承了类B和类C,当子类的父类中有共同的祖先时,这种称为钻石继承1、类B和类C中都各自有类A的内容2、类D会继承类B和类C中的所有内容,就会导致类D中有两份类A的内容3、当类D对象去访问类A中的成员时,编译器会产生歧义,不确定要使用的是哪份类A中的成员,因此编译不通过
3、虚继承当使用 virtual 关键字修饰继承表时,此时变成虚继承,此时子类中就会多一个虚指针用于指向父类的内容,当这个子类被继承时,孙子类中也会继承该虚指针,并且通过虚指针比较是否含有多份相同的祖先类,如果有则只保留一份因此:通过虚继承可以在钻石继承中解决子类有多份祖先类成员的问题

六、虚函数和覆盖

1、虚函数当成员函数前加 virtual 修饰后,这样的函数称为虚函数,该类也会像虚继承一样多了一个虚指针
2、虚函数表虚指针指向一张表格的首地址,该表格中记录的是该类中所有虚函数的首地址((void(*)(void))(*(int*)*(int*)b))();//相当于调用了虚函数表中的第一个函数
3、覆盖(重写)当使用virtual关键字修饰父类的成员函数,此时父类中多了一个虚指针(虚表指针),子类会把父类的虚指针一起继承过来,当子类中有与父类虚函数同名的成员函数时,编译器会比较这两个函数的格式,如果格式完全相同,则会把子类的同名函数的地址覆盖掉虚函数表中父类的同名虚函数的原地址此时使用父类的指针或引用指向子类对象时,调用虚函数则会调用被覆盖后的虚函数表中所指向的子类的同名且格式相同的成员函数4、构成覆盖的条件:1、必须是发生在父子类,且一定为public继承2、要被覆盖的父类的函数必须为虚函数 virtual 修饰3、子类中必须有与父类虚函数同名,且返回值、参数列表、常属性都必须完全相同的函数,才能构成覆盖4、覆盖要求返回值类型相同,或者子类函数的返回值类型可以向父类虚函数的返回值类型做隐式转换且有继承关系时,也可以构成覆盖常见面试题:重载、覆盖、隐藏、重写的区别?隐藏:1、如果同名但格式不同,无论是否加virtual,在子类中都会隐藏父类同名成员函数2、子类中如果同名且格式相同,不加virtual,子类也会隐藏父类的同名成员函数总结:父子类中,同名成员函数要么构成覆盖,要么构成隐藏

七、多态

什么是多态:是指同一个事物、指令可以有多种形态,当调用同一个指令时,它会根据参数、环境的不同会做出不同的响应操作,这种模式称为多态C++中根据确定执行操作的时间,多态分为编译时多态、运行时多态编译时多态:当调用重载过的函数时,编译器会根据参数的不同,在编译时就能确定执行哪个版本的重载函数,这种叫做编译时多态,还有模版技术运行时多态:在父子类中,当子类覆盖了父类的同名虚函数,然后用父类指针或引用访问虚函数时,它既可能调用父类的虚函数,也可能调用子类的同名函数,具体调用哪个取决于该父类指针或引用指向的目标是谁,而这个目标的确定需要在运行时才能最终确定下来,这种情况叫做运行时多态构成运行时多态的条件:1、父子类之间且有构成覆盖关系的同名函数2、子类是以public继承父类(让父类指针、引用指向子类对象)3、通过父类指针或引用访问被覆盖的虚函数思考:构造函数和析构函数能否是虚函数?为什么?

八、虚构造和虚析构

虚构造:构造函数不能设置为虚函数,假如构造函数可以设置为虚函数,子类的构造函数会自动覆盖父类的构造函数,当创建子类对象时,子类执行自己的构造函数之前先执行父类的构造函数,但是此时父类的构造函数已经被覆盖成了子类的构造函数,就会再次调用子类的构造函数,这样就形成了死循环,因此编译器不允许把构造函数声明为虚函数
虚析构:析构函数可以设置为虚函数,当使用类多态时,通过父类指针或引用释放子类对象时,默认情况下不加虚析构是不会调用子类的析构函数,如果子类析构函数中有要释放的资源时,就可能构成内存泄漏只有把父类的析构函数定义为虚析构(子类的析构函数会自动覆盖父类的析构函数),当通过父类指针或引用释放子类对象时,会先调用覆盖后的子类析构函数,而且之后还会自动调用父类的析构函数,这样就不会有内存泄漏了总结:当使用多态且子类的构造函数中有申请内存,此时父类的析构函数一定要设置为虚析构

九、纯虚函数和纯抽象类

纯虚函数的格式:virtual 返回值 成员函数名(参数列表) = 0;
1、纯虚函数可以只声明不实现(一般也没必要去实现它)
2、父类中如果有纯虚函数,子类就必须覆盖父类的纯虚函数,否则无法创建对象
3、有纯虚函数的类是无法创建对象的,因为这样的话纯虚函数没有被覆盖
4、纯虚函数的目的就是为了强制子类去覆盖父类的纯虚函数,强制子类实现某些功能
5、有纯虚函数的类称为抽象类
6、析构函数不能定义为纯虚函数纯抽象类:所有的成员函数都是纯虚函数的类,叫做纯抽象类,这种类一般用于设置功能的接口,也称为接口类工厂模式:了解什么是工厂模式,尝试实现一个简单的工厂模式例子

C++继承、虚函数、覆盖、多态、纯虚函数相关推荐

  1. 初入c++(六)虚函数实现多态,虚析构函数,虚函数表和多态实现机制,纯虚函数。

    1.c++多态的概念以及用途. 1.1虚函数实现多态 通过基类指针只能够访问派生类的成员变量,不能够访问派生类的成员函数. 解决问题的办法:使用虚函数(virtual function),只需要在函数 ...

  2. C/C++基础语法复习(三):C++重载函数,多态,虚函数

    1.重载运算符和重载函数: C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载. 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它 ...

  3. 虚函数,虚基类 与纯虚函数 二

    虚函数    还是先看代码 class A { public:     void funPrint(){cout<<"funPrint of class A"<& ...

  4. 析构函数可以为纯虚函数吗?纯虚函数可以有函数体吗?纯虚函数需要函数体吗?

    先回答标题中中的几个问题: 析构函数可以为纯虚函数吗? yes. 纯虚函数可以有函数体吗? yes. 纯虚函数需要函数体吗? 一般来讲,如果析构函数是纯虚函数,那么析构函数必须要有函数体,如果是其它函 ...

  5. c++基础学习(08)--(继承、重载、多态、虚函数)

    文章目录 目录 1.继承 2.重载 3.多态 && 虚函数 目录 1.继承 #include <iostream>using namespace std;// 基类 cla ...

  6. C++编程进阶2(编译器在类内默认生成的函数讨论以及纯虚析构函数)

    三.编译器默认提供的类内函数讨论 1.当写下一个空类时,编译器会在必要的时候默认提供四个函数:构造.拷贝构造.operator=和析构函数,而且都是public的 class Empty{ }; 上述 ...

  7. C++ 虚函数成员和纯虚函数

    一般虚函数成员的声明语法是: virtual 函数类型 函数名(形参表); 在类的定义使用virtual关键字来限定成员函数,虚函数声明只能出现在类定义中的函数原型声明中,而不能在成员函数实现的时候出 ...

  8. 虚函数,虚基类 与纯虚函数 一

    正文 虚基类    在说明其作用前先看一段代码 class A { public:     int iValue; }; class B:public A { public:     void bPr ...

  9. java的虚方法_Java多态和虚方法调用

    多态(polymorphism) 多态的概念 ·多态是指一个程序中相同的名字表示不同的含义的情况. ·多态有两种情形: 1.编译时多态: 1.重载(overload)多个同名的不同方法: 2.如:p. ...

最新文章

  1. 微信新版支持读取iPhone M7/M8协处理器运动数据 与好友PK一下运动量吧
  2. css布局左右2边固定,中间自适应
  3. 8年,永洪科技凭什么跑出中国BI领军速度?
  4. Basic64 编码解码
  5. 将$type添加到System.Text.Json序列化中,就像Newtonsoft那样用于动态对象属性
  6. C++ 拷贝构造 与 赋值运算符重载
  7. light4java_Light Weight Component Library for Java
  8. 几个北大和南开学霸公众号,值得学习
  9. 企业互联网+转型实战:如何进行PB级别数据的架构变迁
  10. 基模高斯光束matlab_MATLAB 高斯光束传播轨迹的模拟
  11. 为什么说Redis单线程效率高
  12. 《缠中说禅108课》44:小级别背驰引发大级别转折
  13. [ERROR] The distro “Ubuntu“ has running processes and can‘t be operated. “wsl -t <name>“ ......
  14. 2021年 全网最细 Windows 系统安装虚拟机Vmware15 及 CentOS7系统和远程登录
  15. python如何输出日期_Python日期常用操作
  16. Metaq的一些简单机制
  17. MMA9553L/MMA955L 计步器快速使用指南
  18. 赛码练习编程题后台 动态规划——上台阶
  19. java is as,as-is是什么意思
  20. ipfs搭建mysql_【IPFS + 区块链 系列】 入门篇 - IPFS环境配置

热门文章

  1. 外挂 制作之0D使用---主要是中断操作
  2. NumPy实现简单的神经网络分析Mnist手写数字库(三)之划分迷你批(mini-batch)
  3. 创造虚拟环境报错An unexpected error has occurred. Conda has prepared the above report.解决方案
  4. oracle用户迁移数据
  5. 石头剪刀布的python代码
  6. windows 部分热键集锦
  7. isee中怎么样创建HTML相册,用isee  一分钟快速作图
  8. java 字节转字符_Java 字符串 之 字符,字节,字符串的转换
  9. Python Spider
  10. 返利指定服务器,忘川风华录返利指定服务器是什么意思,返利指定服务器领取方法...