多态原理
来源:互联网 发布:咸鱼淘宝二手网 编辑:程序博客网 时间:2024/06/07 02:20
1、多态原理的实现
我们知道多态实现的三个条件:1.继承,2.虚函数重写,3.父类指针或引用指向子类对象
当类中有一个函数是虚函数,会在类中增加一个 虚函数指针,虚函数指针会指向一个虚函数表; 虚函数表是一个存储类成员函数指针的数据结构; 虚函数表是由编译器自动生成与维护的; virtual成员函数会被编译器放入虚函数表中; 存在虚函数时,每个对象中都有一个指向虚函数表的指针(vptr)
void func(){}virtual void func () // print (A * const this)调用:p->func(); // p->vfptr->func()
调用虚函数过程
最后在调用的时候,编译器就会根据func是否为虚函数来进行相应的解释: 1.如果不是虚函数:编译器可直接确定被调用的成员函数(也叫做静态联编) 2.如果是虚函数:编译器根据对象p的VPTR指针所指向的虚函数表中来查找func函数并调用(也叫做动态联编或者迟邦定),也可以说是通过该指针去取 这块地址上的 虚函数指针,通过虚函数指针 去 虚函数表中 去取同名函数
注意:通过虚函数表指针VPTR调用重写函数是在程序运行时进行的,因此需要通过寻址操作才能确定真正应该调用的函数,而普通成员函数是在编译器时就确定了调用谁,因此虚函数的效率要低很多,所以不是虚函数越多越好。C++编译器,执行run函数,不需要区分是子类对象还是父类对象
2、构造函数中调用虚函数能否实现
构造的顺序是先构造父类、再构造子类
当调用父类的构造函数的时候,虚函数指针vfptr 指向父类的虚函数表
当父类构造完,调用子类的构造函数的时候,虚函数指针 vfptr 指向子类的虚函数表
结论:构造函数中无法实现多态
class A{public: A() { // 在构造函数中调用虚函数是不能实现多态的 // 虚函数指针 是分步初始化,一开始指向父类的虚函数表,父类初始化完了以后 指向自己的虚函数表 print(); } virtual void print() { printf ("AAAAAAAAAAAAAAAAAAAAA\n"); }public: int a;};
3、不要用父类指针指向子类数组
指针也是一种数据类型,C++类对象的指针p++/–,仍然可用。
指针运算是按照指针所指的类型进行的。
父类p++与子类p++步长不同;不要混搭,不要用父类指针++方式操作子类对象数组
下面这个案例可以看出:
class A{public: A(int a) { this->a = a; } virtual void print() { printf ("a = %d\n", a); }public: int a;};class B:public A{public: B(int a, int b): A(a) { this->b = b; } virtual void print() { printf ("a = %d, b = %d\n",a, b); }public: int b;};int main(){ B b[5] = {B(1,2), B(3,4), B(5,6), B(7,8), B(9,10)}; B *pb = b; A *pa = b; // 一般来讲 基类 和 派生类 的指针步长是不一样的, 除非派生类没有增加任何成员 // pa + 1 = pa + sizeof(A) pb + 1 = pb + sizeof(B) // 不要基类的指针 操作派生类的数组 for (int i = 0; i < 5; i++) { // pb[i].print(); // pa[i] ==> pa + i ==> (int)pa + sizeof(A) ==> (int)pa + 8 // sizeof(B) = 12 pa[i].print(); // long * p = 0x100000 ==> p + 1 = 0x10004 ==> (long)p + 1 = 0x10001 } return 0;}
- RTTI实现原理(多态的原理)
- 多态原理
- 多态原理
- C++多态原理
- 多态实现原理
- 多态实现原理
- c++多态原理
- 多态原理分析
- 多态实现原理
- 多态原理
- 多态原理
- 多态的实现原理
- c++ 多态原理笔记
- java多态原理介绍
- Java多态实现原理
- 多态实现的原理
- java多态实现原理
- 多态的实现原理
- 关于php读取数据库以及网页显示问题
- jqGrid的rownum属性
- TP5 如何接收表单多选框(type="checkbox")
- 百度OCR识别初体验
- matlab 生成二维或三维空间中满足正态分布的样本点,并绘图
- 多态原理
- 软件工程的生命周期
- Swift4.0 — 属性
- Storm Streams
- 使用raise语句自己触发异常
- (二)文件I/O 3.creat函数和close函数
- LwIP动态内存管理
- mathematica StringCases和StringReplace,Regex
- 【深度学习】初始化笔记