需要实现多态必不可少的就是虚函数,类的成员函数前加virtual关键字,这个成员函数就是虚函数;例如:
class T{ public: virtual void fun() { cout<<"fun()"<<endl; } int _t;};在不加virtual的情况下:sizeof(T)的大小为4;加了vitual变成虚函数之后:sizeof(T)的大小为8;这是为什么呢?? 存在虚函数的类的对象模型为:
由此图可以看出T的对象中不仅有_t而且还有一个指针,这个指针指向的是一个存放虚函数地址的表,也就是虚表。所以在类成员函数前加了virtual之后的大小为8;根据下图就可以看出虚表中是怎么去存放虚函数的地址:
在单继承下的虚函数表又是什么样??
class T{public: virtual void fun1() { cout << "T::fun1()" << endl; } virtual void fun2() { cout << "T::fun1()" << endl; } int _t;};class Z : public T{public: virtual void fun1() { cout << "Z::fun1" << endl; } virtual void fun3() { cout << "Z::fun3" << endl; } int _z;};上述代码中,类Z单继承T,重写了T类中的fun1,fun2并没有重写,在Z类本身中还加了自己的虚函数fun3;Z的对象模型为:
vs2013监视窗口:
由上图监视窗口可以看出在__vfPtr所指的虚表中只有Z::fun1和T::fun2这两个虚函数的地址,fun3并没有存在于虚表中,这是因为vs2013下编译器的一个bug,不过我们换一种方式(打印虚表)来看虚表:
class T{public: virtual void fun1() { cout << "T::fun1()" << endl; } virtual void fun2() { cout << "T::fun1()" << endl; } int _t;};class Z : public T{public: virtual void fun1() { cout << "Z::fun1()" << endl; } virtual void fun3() { cout << "Z::fun3()" << endl; } int _z;};typedef void (*V_F) ();void PRintVtable(int vptr){ int * ptr = (int *)vptr; printf("虚表:0x%p/n",ptr); for (int i = 0; ptr[i] != 0; i++) //通常虚表以0为结束标志; { V_F f = (V_F)ptr[i]; f(); }}void test(){ Z z; PrintVtable(*(int*)(&z));}运行截图:
多继承的虚函数表:
class T{public: virtual void fun1() { cout << "T::fun1()" << endl; } virtual void fun2() { cout << "T::fun2()" << endl; } int _t;};class Z {public: virtual void fun1() { cout << "Z::fun1()" << endl; } virtual void fun2() { cout << "Z::fun2()" << endl; } int _z;};class P : public Z,public T{public: virtual void fun1() { cout << "P::fun1()" << endl; } virtual void fun3() { cout << "P::fun3()" << endl; }};typedef void (*V_F) ();void PrintVtable(int vptr){ int * ptr = (int *)vptr; printf("虚表:0x%p/n",ptr); for (int i = 0; ptr[i] != 0; i++) //通常虚表以0为结束标志; { V_F f = (V_F)ptr[i]; f(); }}void test(){ P p; PrintVtable(*(int *)(&p));}运行截图:
可以看出在虚函数表中没有出现虚函数T::fun2();这是因为派生类中的虚函数会放在第一个继承的虚表中;
新闻热点
疑难解答