我在前些天发过《关于MFC消息映射表与虚函数的效率问题》这个帖子,得到了很多朋友的指点,同时我也发现很多比我更新的编程新手对于其中关于虚函数表的实现 一知半解,所以我觉得还是把我自己的
新手心得 发出来,让更多的新接触编程的朋友了解虚函数的实现。
如有错误,敬请指正。
虚函数表是针对类设计的,每个类的所有对象都共享一份虚函数表,每个对象中都有一个
指针成员变量 指向这个 类类型 的虚函数表。
我 猜测 这个虚函数表应该是类的静态成员,且为private不允许修改。
在VS中做个小实验就可以得出来。大家请耐心看下去。
1.设计带有虚函数的基类和重写了这个虚函数的派生类。
2.定义对象,并初始化,在初始化后的任意语句设置断点,启动调试
3.在“局部窗口”里面,点开 局部对象 左边的加号,里面第一个成员就是虚函数表,这是编译器为我们加上去的。
4.而这个虚函数表不是整个链表类型,在最后一列的类型中可以明确看到 这是个
指针类型。
5.在第二栏里面可以看到 这个指针存储的值
#include<iostream>
using namespace std;
class Base
{
public:
void virtual func1()
{
cout<<"Base function1"<<endl;
}
void virtual func2()
{
cout<<"Base function2"<<endl;
}
};
class Derive:public Base
{
public:
void virtual func1()
{
cout<<"Derive function1"<<endl;
}
};
int main()
{
Base *pObj=new Derive();
return 0;
}
根据以上步骤打开虚函数表,我想大家就会明白了,虚函数表里面存储的是这样的数据.
__vfptr指向const Derive::'vftable'
而Derive::'vftable'里面又是怎么存储的呢?
vftable[0]=
Derive::func1(void)
vftable[1]=
Base::func2(void)
所以,其实所有的相同类的对象享有的都是同样的虚函数表。
他们的多态行为,其实也是一成不变的---在他们的类类型定义完之后。
通过作用域限定符,就可以明确指出这个类型的对象到底应该调用哪个版本的虚函数了,仅仅加一个类作用域操作符而已。