C++虚函数原理及函数调用栈模型

  精简原文:http://blog.csdn.net/haoel/article/details/1948051/

  关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议。

  对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表Virtual Table)来实现的。简称为V-Table。在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。

  1.Base中3个虚函数,Derive中3个虚函数:

  1)虚函数按照其声明顺序放于表中。

  2)父类的虚函数在子类的虚函数前面。

  2.Derive重载f()后:

 

  1)覆盖的f()函数被放到了虚表中原来父类虚函数的位置。

  2)没有被覆盖的函数依旧。

 

  3.多重继承后:

  1)  每个父类都有自己的虚表。

  2)  子类的成员函数被放到了第一个父类的表中。(所谓的第一个父类是按照声明顺序来判断的)

  4.函数调用栈模型

具体来说,从内存的角度看,函数h调用f时,Stack是按下面步骤发生变化的:

  1. 实参按照从右向左的顺序一个一个进入stack中。
  2. 函数调用指令之后的“下一条指令地址”进入stack中。(pRetAddr)
  3. EBP(栈指针)指向调用此函数的函数栈地址。(FuncB's EBP)
  4. 函数f中的局部变量加入到stack中。
  5. 函数f中的局部变量从Stack中弹出。
  6. “下一条指令地址”从stack中弱出,流入程序计数器寄存器IP中。
  7. 寄存器AX/EAX/RAX中的值流入到stack中h的局部变量(或者全局变量等)中。(返回值)
  8. 调用函数f时的实参从stack中弹出。

 

posted on 2013-11-13 15:02  依蓝jslee  阅读(378)  评论(0编辑  收藏  举报

导航