C/C++多态及其实现原理

C/C++多态及其实现原理
多态的介绍
多态含义为一个事物有多种形态。在C ++程序设计中,多态性是指具备不一样功能的函数能够用同一个函数名,这样就能够用一个函数名调用不一样内容的函数。通常来讲多态分为两种:html

静态多态:也称为编译时多态,主要包括参数多态,过载多态和强制多态。参数多态:采用参数化模板,经过给出不一样的类型参数,使得一个结构有多种类型。如 C++语言中的函数模板和类模板属于参数多态。参数多态又叫静态多态,它的执行速度快,异常少,调用在编译时已经肯定。过载多态:同一个名字在不一样的上下文中所表明的含义不一样。典型的例子是运算符重载和函数重载。强制多态:编译程序经过语义操做,把操做对象的类型强行加以变换,以符合函数或操做符的要求。程序设计语言中基本类型的大多数操做符,在发生不一样类型的数据进行混合运算时,编译程序通常都会进行强制多态。程序员也能够显示地进行强制多态的操做。如 int+double,编译系统通常会把 int 转换为 double,而后执行 double+double 运算,这个int->double 的转换,就实现了强制多态,便可是隐式的,也可显式转换。强制多态属于静态多态。
 
动态多态:也称运行时多态,主要包括:包含多态。包含多态的基础是虚函数。主要是经过类的继承和虚函数来实现,当基类和子类拥有同名同参同返回的方法,且该方法声明为虚方法,当基类对象,指针,引用指向的是派生类的对象的时候,基类对象,指针,引用在调用基类的方法,实际上调用的是派生类方法。
重载多态和强制多态是指特定多态, 重载多态和强制多态称为特殊多态性,用来刻画语义上无关联的类型间的关系;参数多态和包含多态是指通用多态,类型参数化多态和包含多态称为通常多态性,用来系统地刻画语义上相关的一组类型。程序员

静态多态实现
静态多态靠编译器来实现,简单来讲就是编译器对原来的函数名进行修饰。能够根据函数参数的类型,个数,以及修饰函数const,这就使得函数能够重载。同理,模板也是能够实现的,针对不一样类型的实参来产生对应的特化的函数,经过增长修饰,使得不一样的类型参数的函数得以区分。函数

动态多态的实现
动态多态靠运行时的类型检查,从而来进行函数的绑定。声明一个类时,若是类中有虚方法,则自动在类中增长一个虚函数指针,该指针指向的是一个虚函数表,虚函数表中存着每一个虚函数真正对应的函数地址。动态多态采用一种延迟绑定技术,普通的函数调用,在编译期间就已经肯定了调用的函数的地址,因此不管怎样调用,老是那个函数,可是拥有虚函数的类,在调用虚函数时,首先去查虚函数表,而后在肯定调用的是哪个函数,因此,调用的函数是在运行时才会肯定的。.net

虚表指针初始化问题
当建立子类对象时,编译器的执行顺序实际上是这样的:设计

对象在建立时,由编译器对 vptr 进行初始化
子类的构造会先调用父类的构造函数,这个时候 vptr 会先指向父类的虚函数表
子类构造的时候,vptr 会再指向子类的虚函数表
对象的建立完成后,vptr 最终的指向才肯定
虚函数表的构成
具体的详细细节见https://blog.csdn.net/wenqiang1208/article/details/53148486指针

https://www.cnblogs.com/longcnblogs/archive/2017/10/09/7642951.htmlhtm

无覆盖的公有单继承:虚函数按声明顺序存在于虚表中; 在派生类中,前面是基类的虚函数,后面是派生类的虚函数。
有覆盖的公有单继承:先拷贝基类的虚表;若是派生类重写了基类的虚函数,则修改同位置的基类虚函数;最后面是生类新定义的虚函数。
单继承的派生类的大小:虚表指针+ 基类的数据成员 + 派生类的成员对象

多重继承:
多重继承派生类的大小:(例若有两个父类)——基类1的虚表指针+基类1的成员变量+基类2的虚表指针+基类2的成员变量+子类成员变量blog

若是派生类有新定义的虚函数,则存放在继承顺序第一的基类续表的最后面。继承

菱形继承


若是派生类有新的虚函数,则添加在第一继承顺序的续表最后面。菱形继承存在二义性,因为直接父类都继承了祖父类的成员变量——致使修改一处,而另一处没有修改(引发数据不一致性)。

虚继承中的单继承
1. 没有构造函数和析构函数(少中间的0——所占的字节),派生类有新的虚函数

2. 没有构造函数和析构函数(少中间的0——所占的字节),派生类没有新的虚函数

3. 有构造函数和析构函数(多中间的0——所占的字节),派生类有新的虚函数

虚继承中派生类的构造函数作了什么

虚继承中的多继承
  没有考虑构造函数或析构函数 ,派生类定义了新虚函数

虚继承中的菱形继承 没有考虑构造函数或析构函数 ,派生类定义了新虚函数

相关文章
相关标签/搜索