C++多态的本质
2016-04-05 12:54
387 查看
我们先谈谈单继承的情况:
1.编译器能否识别多态,看是否有virtual关键字,如果有,那么在声明对象的时候,内存会分配一个vptr关键字和一个vptb表,其中vptr指向vptb表。
假定某一个虚函数f(),放在vptb的slot(2)中,一个虚函数g()凡在slot(3)中,当基类声明了一个虚函数,并且有子类继承基类的时候会出现二种情况:
1.基类的虚函数f()被子类重写,此时,子类有一个VPTR指针指向vptb表,在子类的vptb表的slot(2)中,也有一个f()函数,不过此时的f()函数类型是子类的。
2.基类的虚函数f()没有被子类重写,此时,子类有一个VPTR指针指向vptb表,在子类的vptb表的slot(2)中,也有一个f()函数,不过此时的f()函数类型是基类的。
那么有以上2点,在多态实现编译期就可以知道虚函数的偏移地址,唯一不知道的就是,是哪一个VPTR表的虚函数,那么这个问题会在执行期搞定。
例如
ptr->f();
会被转化为
(*ptr->vptb[2])(ptr);
有vptr[2]我们已经知道了去执行哪一个函数,唯一不知道的就是,哪一个虚函数表的vptr[2].
在编译器的执行期,会告诉编译器去执行哪一个虚函数表,那么此时就完成了多态。
多继承的情况:
多继承的情况下,派生类内部的情况比较复杂,主要是:
1.产生了n个vptb表,其中n-1个是额外的vptb表;
2.第一个vptb是主要的表格,继承着第一个基类的vptb。
3.后面n-1个是次要的表格。
当基类base1的指针指向派生类的时候,那么和单继承的情况是一样的。
当基类base2的指针指向派生类的时候,那么会有指针地址的调整,像前调整(sizeof(base1))个单位。这些都是在执行期完成的。
1.编译器能否识别多态,看是否有virtual关键字,如果有,那么在声明对象的时候,内存会分配一个vptr关键字和一个vptb表,其中vptr指向vptb表。
假定某一个虚函数f(),放在vptb的slot(2)中,一个虚函数g()凡在slot(3)中,当基类声明了一个虚函数,并且有子类继承基类的时候会出现二种情况:
1.基类的虚函数f()被子类重写,此时,子类有一个VPTR指针指向vptb表,在子类的vptb表的slot(2)中,也有一个f()函数,不过此时的f()函数类型是子类的。
2.基类的虚函数f()没有被子类重写,此时,子类有一个VPTR指针指向vptb表,在子类的vptb表的slot(2)中,也有一个f()函数,不过此时的f()函数类型是基类的。
那么有以上2点,在多态实现编译期就可以知道虚函数的偏移地址,唯一不知道的就是,是哪一个VPTR表的虚函数,那么这个问题会在执行期搞定。
例如
ptr->f();
会被转化为
(*ptr->vptb[2])(ptr);
有vptr[2]我们已经知道了去执行哪一个函数,唯一不知道的就是,哪一个虚函数表的vptr[2].
在编译器的执行期,会告诉编译器去执行哪一个虚函数表,那么此时就完成了多态。
多继承的情况:
多继承的情况下,派生类内部的情况比较复杂,主要是:
1.产生了n个vptb表,其中n-1个是额外的vptb表;
2.第一个vptb是主要的表格,继承着第一个基类的vptb。
3.后面n-1个是次要的表格。
当基类base1的指针指向派生类的时候,那么和单继承的情况是一样的。
当基类base2的指针指向派生类的时候,那么会有指针地址的调整,像前调整(sizeof(base1))个单位。这些都是在执行期完成的。
相关文章推荐
- C#与.net高级编程 C#的多态介绍
- C#中面向对象编程机制之多态学习笔记
- C#中的多态深入理解
- C#中多态、重载、重写区别分析
- 设计引导--一个鸭子游戏引发的设计理念(多态,继承,抽象,接口,策略者模式)
- C# 面向对象三大特性:封装、继承、多态
- javascript每日必学之多态
- c#基础学习之多态
- PHP面向对象三大特点学习(充分理解抽象、封装、继承、多态)
- 从汇编看c++中多态的应用
- javascript 面向对象全新理练之继承与多态
- Java多态的使用注意事项
- C#使用虚拟方法实现多态
- 实例讲解PHP面向对象之多态
- C#中多态现象和多态的实现方法
- C++基础之this指针与另一种“多态”
- 深入解析C++中的虚函数与多态
- C++多态的实现及原理详细解析
- PHP5中实现多态的两种方法实例分享
- 举例讲解PHP面对对象编程的多态