多态性
c++有两种多态性:
1. 编译时的多态 编译时的多态是指函数重载(早起绑定)来实现的也成为早起绑定
2.运行时的多态
运行时的多态性是指在程序执行前,无法根据函数名和参数来确定该调用哪一个函数,必须在程序执行过程中,根据执行的具体情况来动态的确定;他是通过类的继承关系public和虚函数来实现的,目的也是建立一种通用的程序;通用性是程序追求的主要目标
通过引用或者指针的调用时,才能达到多态
赋值兼容规则:(公有继承是前提)//("是一个")
- 派生类对象可以赋值给基类对象
- 派生类对象的指针可以赋值给基类的指针
- 派生类对象可以初始化基类对象的引用
必须传指针和引用的原因: 调动指针和引用才能调用续表指针在虚函数中查虚表
虚函数是一个类的成员函数
派生类中的虚函数与基类中的虚函数必须是同名、同参数列表、同返回类型,否则被认为是重载(同名函数的隐藏)【若为基类中虚函数返回基类指针,派生类中虚函数返回派生类指针也可以视作是多态】
静态函数、友元函数、内联函数不可作为虚函数,因为需要有继承关系,所以,所有的构造函数也不会是虚函数,但析构函数可以是虚函数(其派生类的析构函数也会成为虚函数),
多态的发生:
对象名.方法() :静态联编,调用的是对象类型的方法(不论virtual或普通),在编译时期就确定了
对象引用->方法(): 动态联编,则调用对应虚函数表中的virtual方法,在运行时查虚表来确定
静态联编在编译时要确定的东西:①类型 、②可访问属性 、③函数参数的默认值,而动态联编在调用方法时,也是在编译时先确定以上三者,但调用时会动态地确定调用的方法。
如果我们先构造test对象时
1.先开辟4+4+4+4的空间(隐藏类和虚表指针也算)
2执行构造函数的时候先填obj的虚表(这就是为什么构造函数不能当虚函数的原因既要查表又要填表就会产生矛盾),在填充value的值
3.在构造base的构造函数,这时我们不需要将在创建虚表了,系统会将虚表指针拷贝下来,将之前obj拥有的虚函数拷贝下来,如果base里面也拥有同名同参数类型同返回值的虚函数,那么就将会覆盖基类的虚函数,(同名覆盖),没有的就简单的拷贝下来就行了,base里面还加有虚函数就直接填入虚表中,如果将对象的指针和引用传进去时,就会查表
4构造test函数跟base同理,先将指向虚表的指针拷贝下来,然后进行填表,将base类的虚表拷贝下来,同名同参数类型同返回值的虚函数就将其覆盖掉,与构建base指针类似