关于虚函数调用之我的一点理解

先来看普通函数调用。

有类如下:
class A 
public: 
 
void callfunc(int a,int ,int ) 
printf("A::callfunc\r\n"); 
 
}; 
 
 
int main() 
A *pA=NULL;
pA->callfunc();
return 0; 
惊奇地发现,调用函数无需任何空间,无需实例化类,只需定义一个类A的指针即可,这说明了,类内函数的调用,不依靠对像传递任何东西。只要编译器识别到指针的类型(属于哪个类)即可。
 
当然,有一种情况例外,那就是。。。虚函数
看以下代码:
#include
#include
 
class A 
public: 
void f1() 
printf("A::f1\r\n"); 
virtual void f2() 
printf("A::f2\r\n"); 
void callfunc() 
printf("A::callfunc\r\n"); 
f1(); 
f2(); 
}; 
class B :public A 
public: 
int aabb;
void f1() 
printf("B::f1\r\n"); 
void f2() 
printf("B::f2\r\n"); 
void callfunc() 
printf("B::callfunc\r\n"); 
f1(); 
f2(); 
void fb()
{
;
}
}; 
 
int main() 
 
B *pB=new B; 
A *pA=NULL;
pA=pB;
pA->callfunc();
 
return 0; 
若此时去掉pA=pB将会在类A中的f1(),f2()报错,答案是。。。虚函数和普通函数是不一样的,执行虚函数需要v-table,程序执行到f1(),f2()发现虚函数,但没有v-table无法从找到函数入口地址,故直接报错,那为毛pA=pB就可以正确执行了呢?又为毛输出的是A的callfuncB的f1,f2呢?
一般地,对像起始地址存的是vptr,这个指针指向的是v-talbe,可以通过v-table(函数指针数组,只存虚函数,有虚函数的类必定有v-talbe)去索引虚函数入口地址列表,当然,是B的v-table。故函数执到类A的f1() f2()时,先从pA的起始地址(即pB的起始地址)获得了vptr,再据vptr找到对对应类的v-talbe,从v-talbe中找到了B类的函数,故这之后直接跳到B类去了。

 

posted @ 2013-01-11 23:13  yurius  阅读(236)  评论(0编辑  收藏  举报