博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ 类的多态三(多态的原理--虚函数指针--子类虚函数指针初始化)
阅读量:6653 次
发布时间:2019-06-25

本文共 2079 字,大约阅读时间需要 6 分钟。

//多态的原理--虚函数指针--子类虚函数指针初始化#include
using namespace std;/*多态的实现原理(有自己猜想部分)基础知识: 类中的成员函数本质上是C语言中的全局函数,只是在全局函数的参数列表中多加了一个结构体指针参数详解: 对于类中没有用virtual关键字修饰的成员函数,c++编译器在静态编译的时候,c++就会确定对象调用的全局函数 当类中声明虚函数时,c++编译器会在静态编译的时候为这个类生成一个虚函数表, 虚函数表是一个存储类成员函数指针的数据结构, 一个虚函数表只属于一个类 虚函数表是由编译器自动生成与维护的 virtual成员函数的地址会被c++编译器放入虚函数表中 在定义一个对象的时候即运行时或者说动态编译的时候(未调用构造函数之前)---Point p1; , 那么c++编译器会为这个对象 隐式的 分配4个字节大小的内存, 这个内存里是一个 指针变量 此时这个指针变量还是为NULL,当执行函数的构造函数的时候 c++编译器会默认的为这个指针变量赋值 这个指针变量会指向该类的虚函数表 对于子类而言,子类的初始化比较特殊,必须先调用父类的构造函数,这时候这个隐藏的指针变量会被初始化为父类中虚函数表的地址 随后子类对象又会再次调用自身的构造函数 这个隐藏的指针变量又会再一次被赋值为 子类 对应的类的虚函数表的地址 说明1: 通过虚函数表指针VPTR调用重写函数是在程序运行时进行的,因此需要通过寻址操作才能确定真正应该调用的函数。 而普通成员函数是在编译时就确定了调用的函数。在效率上,虚函数的效率要低很多。 说明2: 出于效率考虑,没有必要将所有成员函数都声明为虚函数*/class Point{public: Point(){ PrintA(); } virtual void PrintA(){ cout << "1 我是第一个父类虚函数 我必将产生占据4个字节大小的函数指针a " << endl; } virtual void PrintB(){ cout << "2 我是第二个父类虚函数 我必将产生占据4个字节大小的函数指针b " << endl; } virtual void PrintC(){ cout << "3 我是第三个父类虚函数 我必将产生占据4个字节大小的函数指针c " << endl; }private: int b;};class PointA :public Point{public: void PrintA(){ cout << "我是子类PointA 我重写了父类的虚函数 " << endl; }};class PointB :public PointA{ void PrintA(){ cout << "我是孙子类 PointB 我重写了字类的重写函数 用来验证子类中的重写函数是不是一个虚函数 " << endl; }};void ProtectA(PointA &pin){ pin.PrintA();}void ProtectB(){ Point p1; cout << "Point类型的大小" << sizeof(p1) << endl; //打印 8 //说明:c++编译器的确为虚函数分配了4个字节大小的内存 并且无论有多少个虚函数,只会分配4个字节大小的内存空间 //侧面证明了 虚函数指针指向的是一个虚函数表 而不是一个虚函数指针指向一个虚函数 PointA pa; cout << "PointA类型的大小" << sizeof(pa) << endl; //打印 8 //根据结果说明:子类重写父类的虚函数,虽然没有加virtual关键字,但是本质上还是一个虚函数 //不然 为什么c++编译器为什么会为子类对象多分配4个字节大小的内存空间呢? //做一下验证 写一个子类PointB 继承 PointA看是否能实现多态 PointB pb; ProtectA(pb);// 打印出PointB 孙子类中的重写函数 //证明: 子类重写父类的虚函数,虽然没有加virtual关键字,但是本质上还是一个虚函数 }void ProtectC(){ //验证子类的分步初始化对虚函数指针的影响----我在父类的构造函数中调用一个虚函数,并且在子类中重写该虚函数 PointA pa;//调用了父类的PrintA()函数 //验证我文章开头结论 pa.PrintB();}void main(){ ProtectC(); system("pause");}

 

转载地址:http://xhjto.baihongyu.com/

你可能感兴趣的文章
Android应用程序键盘(Keyboard)消息处理机制分析(6)
查看>>
skullsecurity作者常用的一些linux命令
查看>>
系统集成工程师--想说爱你不容易
查看>>
同质化严重,手机智能化发展方向今安在?
查看>>
在IIS8添加WCF服务支持
查看>>
对话微信头条产品总监:优质原创内容的个性化推送是如何实现的
查看>>
烂泥:Windows Server 2008如何修改用户的密码
查看>>
自媒体掘金时代已来临,你准备好了吗?
查看>>
Exchange 2013多租户托管PART 5:配置通讯簿策略
查看>>
外部排序(java实现)
查看>>
Android之系统自带的文字外观设置及实际显示效果图
查看>>
Windows_Programing_English_To_Chinese_1_MSVC_C运行库
查看>>
input默认值设置
查看>>
谷歌语言标准中,C++成绝对的佼佼者
查看>>
wcf系列学习5天速成——第三天 事务的使用
查看>>
编程基础-字符篇-(1)
查看>>
深入 Python :Dive Into Python 中文版 重定向
查看>>
Apache+Django性能优化之mod_wsgi篇
查看>>
cocos2d/box2d技术问题汇总
查看>>
mysqldump 常用备份选项,只备份数据或结构的方法
查看>>