如果一个类中存在虚函数的话,那么编译器就会为这个类生成一个虚函数表,这个虚函数表中按照个虚函数的声明顺序存放了各个虚函数的地址,需要注意的是,这个虚函数表并不存在于类中,而对于这个类的每个对象,编译器都会为其生成一个透明不可见的指针,这个指针就是虚函数表指针,位于该对象内存中的开头,并指向了虚函数表的位置。换句话说,如果一个类中存在虚函数,假设声明一个对象a,在32位的编译情况下,对象a的内存布局中前4个字节中就存放了虚函数表的地址。
因此,通过这前4个字节就可以找到虚函数表,而在虚函数表中,按照虚函数的声明顺序存放了各个虚函数地址。
下面,将通过一个例子来阐述整个过程。
首先定义一个类A,其中含有两个整型变量以及3个虚函数。
class A //定义一个类A,类中有3个虚函数
{
public:
int x;
int y;
virtual void f(){ cout << "f() called !" << endl; };
virtual void f1(){ cout << "f1() called !" << endl; };
virtual void f2(){ cout << "f2() called !" << endl; };
};
然后在主函数中声明一个对象a,&a得到对象a的地址。前面说过,对象的内存布局中前4个字节数据为虚函数表的地址,因此将(&a)强制类型转换为(int *),来把从&a开始的4个字节当作一个整体&