C++虚表的实现原理(windows & linux上)

原创 2015年11月21日 20:21:27

当大家被问到C++多态是怎么实现的时候,一般也就想到了虚函数吧,进一步也就是想到了与其关联的虚表指针,那我们就该想想这个虚表到底是怎么做到的呢。

/*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 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() -100

	f = (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上应该加了些保护机制吧,对于基类中有一些其他成员变量的好像不能通过指针计算偏移的方式访问到吧,如果能够做到或者有什么错误希望能留言联系吧

 

 

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

COM接口聚合实现解惑(C++虚表)

本文转自http://blog.csdn.net/nobugtodebug/archive/2009/10/12/4659351.aspx              最近看潘爱民的《COM原理...

C++动多态实现之虚函数与虚表指针

最近在学习C++的动多态时,了解到关于虚函数表与虚表指针的知识点,感觉很有意思,因此总结记录下来(依据个人理解而写,欢迎批评指正)。1、静多态与命名倾轧,动多态与虚函数:(1)概述: 我们知道,C+...

C++ 虚函数实现:虚函数表 虚表指针

virtual(虚函数)的实现

C++多态虚表分析图解

  • 2017-03-14 18:07
  • 134KB
  • 下载

研究虚表(探索多态的原理)和菱形虚拟继承

多态——  一个接口 多种形态, 编译器在执行过程中遇到virtual关键字的时候,将自动安装动态联编需要的机制,首先为这些包含virtual函数的类(注意不是类的实例)--即使是祖先类包含虚函数...
  • seuqi
  • seuqi
  • 2017-02-15 21:38
  • 90

研究虚表(探索多态的原理)和菱形虚拟继承

菱形继承也称钻石继承,具体模型如下 菱形继承代码段如下: 但由于菱形继承仍有两大缺点:二义性与数据冗余,所以由此我们引进菱形虚拟继承来完善这两点

虚函数、虚表原理

http://bbs.chinaunix.net/archiver/?tid-1711337.html 理解虚函数( virtual function )的几个关键点: 1.       理解...

研究菱形虚拟继承和虚表(探索多态的原理)

1.继承 定义的理解         C++中存在继承机制。通过继承,我们可以利用已存在的 数据类型来定义新的数据类型,在新的数据类型中不仅有自己新定义的成员外,还包含以前以前旧的成员,即允许程序员在...

C++13、抽象类和虚表

示例: 运行结果如下: 从结果我们可以看出了,PIX和PIY 只差了4个字节,原因呢?当然那是一个指针的距离,一个虚表指针的距离! 那什么是虚表呢? 答案如下: C++中每个有虚...

C++继承虚表检查

#include #include using namespace std; typedef unsigned int u32; class CMyClassA { public: virt...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)