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

 

 

 

C++ 虚函数、纯虚函数、继承、虚表、多态原理相关知识点总结

虚函数与纯虚函数 虚函数为了重载和多态的需要,在基类中是有定义的,即便定义是空,所以子类中可以重写也可以不写基类中的此函数! 纯虚函数在基类中是没有定义的,必须在子类中加以实现,很像java中...

在类有成员变量的场景下, 按照虚表原理, 模拟虚函数实现

前言 当类没有成员变量的情况下,   类首地址有4个字节的空间, 这里可以放我们模拟出来的虚表入口地址. 当类有成员变量的情况下, 类首地址就是成员变量,  所以, 为了模拟虚表实现, 需要在成员变量...

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

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

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

virtual(虚函数)的实现

虚指针 虚表之c++实现多态的方法

1、c++实现多态的方法 其实很多人都知道,虚函数在c++中的实现机制就是用虚表和虚指针,但是具体是怎样的呢?从more effecive c++其中一篇文章里面可以知道:是每个类用了一个虚表,...
  • cws1214
  • cws1214
  • 2013年03月13日 22:18
  • 1957

C++ virtual函数 实现机制——虚函数地址在虚表中的分布

C++ virtual函数 实现机制中,已经学习了虚函数和虚函数表的机制,但是还是很多细节没解决,这里就探讨一下夹心层的问题。 放例子——虚表跳转,利用虚函数地址强行执行: #include #i...

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

本文转自http://blog.csdn.net/nobugtodebug/archive/2009/10/12/4659351.aspx              最近看潘爱民的《COM原理...
  • arau_sh
  • arau_sh
  • 2011年01月05日 22:59
  • 745

C++多态虚表分析图解

  • 2017年03月14日 18:07
  • 134KB
  • 下载

虚函数、虚表原理

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

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

1.继承 定义的理解         C++中存在继承机制。通过继承,我们可以利用已存在的 数据类型来定义新的数据类型,在新的数据类型中不仅有自己新定义的成员外,还包含以前以前旧的成员,即允许程序员在...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++虚表的实现原理(windows & linux上)
举报原因:
原因补充:

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