C++虚表的实现原理(windows & linux上)
来源:互联网 发布:c语言flag什么意思 编辑:程序博客网 时间:2024/06/06 08:47
当大家被问到C++多态是怎么实现的时候,一般也就想到了虚函数吧,进一步也就是想到了与其关联的虚表指针,那我们就该想想这个虚表到底是怎么做到的呢。
/*author: Jeson Yang date:2015.11.21 file:****.cpp*/#include <iostream>using namespace std;#define __stdcallclass CBase{public:virtual void f(){ cout << "f()" << endl; };virtual void g(){ cout << "g()" << endl; };virtual int i(int nNum){ cout << "i() - " << nNum << endl; return 0; };void m(){ cout << "m()" << endl; };//混淆视听的非虚函数virtual void h(){ cout << "h()" << endl; };};int main(){CBase cb;typedef void(__stdcall *pFun)();typedef int(__stdcall *pFun1)(int);//告诉编译器使用远的C函数吧,不加可能出错喔pFun f;pFun1 f1;int *vPtr = (int*)&cb;//虚表指针喽int *vFun = (int*)((int*)*vPtr + 1);//通过虚表找到的 指向第二个虚函数地址的指针f = (pFun)*vFun;//通过虚表找到的 第二个虚函数地址//f = (pFun)*(int*)((int*)*vPtr + 1);//f = (pFun)*(int*)((int*)*(int*)&cb + 1);f();//打印g()f1 = (pFun1)*(int*)((int*)*vPtr + 2);//跟上面的差不多吧f1(100);//打印i() -100f = (pFun)*(int*)((int*)*vPtr + 3);//函数m在前面,但是不是虚函数,所以跳过喽f();//打印h()//关于越界后面改成+4(算是结束点吧) windows7+vs2013为NULL//linux据说有些环境f值为1表示有下一个虚表,0表示结束吧</span>待考证//本人linux好像结果不一致return 0;}
具体根据这个注释走一遍,关于这种最简单结构的虚表的结构应该能画出来吧。
如果以上能完全理解了,下面就可以看看有多重继承关系的结构了,个人对于画图不怎么在行,也就只好通过注释来理解了,不便见谅。
<pre class="cpp" name="code">/*author: Jeson Yang date: 2015.11.21 file: ****.cpp*/ #include <iostream> using namespace std; #define __stdcall class CBase { public: virtual void f(){ cout << "f()" << endl; }; virtual void g(){ cout << "g()" << endl; }; virtual int i(int nNum){ cout << "i() - " << nNum << endl; return 0; }; void m(){ cout << "m()" << endl; }; //混淆视听的非虚函数 virtual void h(){ cout << "h()" << endl; }; //int m_nNum; //linux上可以打开 }; class CBase1 { public: virtual void f(){ cout << "f1()" << endl; }; }; class cDerive : public CBase,public CBase1 { public: void f(){ cout << "derive f()" << endl; }; //自动虚,覆盖基类的f() private: }; int main() { cDerive cb; typedef void(__stdcall *pFun)(); typedef int(__stdcall *pFun1)(int); //告诉编译器使用远的C函数吧,不加可能出错喔 pFun f; int **vPtr = (int**)&cb; cout << sizeof(cDerive) << endl; f = (pFun)vPtr[0][0]; //通过虚表找到的 指向第一个虚函数地址的指针 f = (pFun)*(int*)(*(int*)((int*)&cb + 0) + 0); //f = (pFun)(int*)&cb; f(); //打印f1(),多态的实现,函数指针的覆盖 f = (pFun)*(int*)(*(int*)((char*)&cb + sizeof(CBase)) + 0); //此处写法为了适应linux(centos5.6 g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-55))上 //打开CBase里面的int参数 //windows上并不适用 f(); //打印f1(),多态的实现,函数指针的覆盖 return 0; }
当然虚表实现也有些不足,假如将以上f()设置private 以上依旧能够访问,这也是十分危险的,故windows linux上都通过
windows上应该加了些保护机制吧,对于基类中有一些其他成员变量的好像不能通过指针计算偏移的方式访问到吧,如果能够做到或者有什么错误希望能留言联系吧
1 0
- C++虚表的实现原理(windows & linux上)
- DDNS 的工作原理及其在 Linux 上的实现
- DDNS 的工作原理及其在 Linux 上的实现
- DDNS 的工作原理及其在 Linux 上的实现
- TCP/IP原理、基础以及在Linux上的实现
- TCP/IP原理、基础以及在Linux上的实现
- TCP/IP原理、基础以及在Linux上的实现
- Linux 电源管理在ARM上的实现原理
- Linux 电源管理在ARM上的实现原理
- TCP/IP原理、基础以及在Linux上的实现
- Windows上C语言实现设置控制台的颜色
- 在LINUX上实现 windows 回收站功能的脚本
- C++ 多态的实现原理--虚函数表
- TCP&UDP C/S在linux上的简单实现
- 浅谈系统安装原理以及在Windows上安装Linux的细节
- gettimeofday windows上的实现
- gettimeofday windows上的实现
- linux上用c实现算术编码(一)--具体操作
- Common Tools
- LintCode-剑指Offer-(373)奇偶分割数组
- 揭开车载导航与手机互联的面纱系列
- ON_REGISTERED_MESSAGE
- 中文 iOS/Mac 开发博客列表
- C++虚表的实现原理(windows & linux上)
- iOS 8星空背景
- 简单Linux C线程池
- iOS开发之UITextView,设置textView的行间距及placeholder
- 对称加密和分组加密中的四种模式(ECB、CBC、CFB、OFB)
- 效率
- 设计模式之单例模式
- 安装ns3的环境准备
- line-ending