一,继承和多态;
类之间的继承;
基类,(父类);
成员变量:描述类的属性
成员函数:功能
派生类(子类)
体现出与基类的不同
继承;基类与派生类之间访问权限
1.public继承
.基类里面的公有成员变量被继承后在派生类中也是公有的(可以在类外被访问);
.基类里面的保护成员变量被继承后在派生类中可以被访问,在派生类中的权限有两种,protect
(子类对象不能在类外访问);
.基类里面的私有成员变量被继承后在派生类中不能被访问,但是已经继承下来(不能在类外访问);、
2.protected继承;
3.private继承;
注意;基类中私有的成员已经被继承到子类中,但是不能直接访问!
访问权限;public > protectd > private;
赋值兼容规则;
1.派生类的对象可以直接赋值给基类的对象,反之不可以。
继承总结;
1.继承概念
2.不同继承方式基类中不同访问权限的成员在子类中权限的改变
3.赋值兼容规则----public
4.同名隐藏(派生类访问不到基类的同名成员了)(要在基类同名成员前加上基类名和作用域限定符)
5.派生类中的默认成员函数
如何让一个类不能被继承?
在基类中,将构造函数设为私有的;派生类的构造初始化不能访问基类的构造函数,同时类外也不能定义一个
基类对象。
关键字;final;
功能;限制类被继承.
菱形继承;单继承和多继承复合
缺陷;存在二义性;
解决二义性;
1.让访问明确化。
2.虚拟继承;
比普的继承多了四个字节
派生类的对象模型 派生类对象模型,派生类对象模型倒立:基类在下,派生类部分在上。
编译器为派生类生成了默认构造函数,作用:在构造函数中必须将对象前四个字节填充完整。
编译器为派生类生成了默认构造函数,作用:在构造函数中必须将对象前四个字节填充完整。
多态;
1.什么是多态?
多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。
在C++中也是如此。同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
C++中,实现多态有以下方法:虚函数,抽象类,覆盖,模板(注意:重载和多态无关)。
2.多态实现的条件;(在继承体系中)
》基类中必须包含有虚函数,派生类必须对基类中的虚函数进行重写。
》虚函数的调用方式:通过基类的指针或引用调用虚函数
表现;多态行为;在程序运行时,安照基类指针指向不同子类对象,调用不同子类的虚函数。
两个条件缺一不可,否则就不能实现多态,不管传递那个类的对象,调用的都是基类的虚函数。
》重写;
派生类重写基类的虚函数(一个在基类中,一个在派生类)
派生类虚函数的原型必须与基类中虚函数的原型(返回值类型,函数名字以及参数列表)完全相同
例外;
协变-----》基类虚函数返回基类的指针或引用
派生类虚函数返回派生类的指针或引用
基类和派生类虚函数的返回值类型不一样
析构函数;
基类中析构函数只要是虚函数,派生类的析构函数定义之后就重写了基类的析构函数
基类和派生类析构函数的名字不同
基类和派生类虚函数的访问权限可以不同;一般将基类的虚函数设置成
public
基类和派生类虚函数的访问权限可以不同;一般将基类的虚函数设置成public
3.关键字;final
final修饰类;---》该类不能被继承;
final虚函数-----》该虚函数不能被派生类重写
关建字;override帮助用户检查是否能重写;
数重载 同名隐藏 重写
4.抽象类;
概念;
包含纯虚函数的类叫做抽象类。不能实例化对象。
如果一个类中包含有虚函数
-1.对象多了四个字节;
-2.该四个字节内容在构造中进行填充
-3.前四个字节中放置一个指针(虚表指针)地址———》指向虚函数
虚函数的存放规则;按照在类中声明的先后次序进行存放
基类虚表的构建规则;
按照虚函数在类中的声明次序将其依次放置在虚表中;
派生类虚表的构建规则;
-1.将基类虚表内容拷贝一份放到派生类虚表中
-2.如果派生类重写了基类某个虚函数,用派生类自己的虚函数替换,虚表中相同偏移量位置的
基类虚函数
-3.对于派生类自己新增加的虚函数将其按照在类中声明的先后次序依次放在虚表的最后。
对虚函数调用
-1.从对象前四个字节中获取虚表的地址
-2.传递this指针
-3.从虚表中获取当前调用虚函数的地址
-4.调用虚函数
5.多态实现原理
类;虚函数--》类的大小—》多了四个字节---》监视窗口——》虚函数地址
派生类:空——》虚表中内容与基类完全相同---》但是虚表指针不同(基类与派生类使用的不是同一张
虚表
6.多态的调用原理:必须满足实现多态的条件
-1.从对象前四个字节中取虚表的地址
-2.给虚函数传参:用户定义参数和this指针
-3.从虚表中找到系函数的地址
-4.调用
内联函数(编译时已经展开)代码可以通过编译,不能实现多态。
静态成员函数为什么不能作为虚拟函数?
虚函数调用---》必须先要找到虚表---》从对象前四个字节中获取虚表指针--->必须要有对象;
静态成员函数没有(this)不能创建对象;
构造函数的作用:初始化对象
如果类中包含虚函数,必须在构造中将虚表指针放在对象的前四个字节中
假设构造函数可以作为虚函数:构造函数--通过虚表调用---》从对象前四个字节去取
构造函数不能作为虚函数。
7.多态分类;静态多态和动态多态
静态多态(静态绑定/早绑定):子啊编译期间,已经确定应该调用那个函数
函数重载 函数模板
动态多态(动态绑定/晚绑定):运行时才确认应该调用那个虚函数
在继承体系中:通过重写基类虚函数。
8.一般情况不会采用继承方式--->实现代码复用
基类
派生列
基类中成员变量以及成员函数继承到子类中