1. 简单虚表实例
C++一个很大的特性就是多态,动态多态就是采用虚函数实现。
对于下面实例,sizeof(A)为4,即一个虚表指针的大小。
-
#include <iostream>
-
using namespace std;
-
class A
-
{
-
public:
-
virtual void vFun1(){cout<<"vFun1() is invoked"<<endl;}
-
virtual void vFun2(){cout<<"VFun2() is invoked"<<endl;}
-
virtual void vFun3(){cout<<"vFun3() is invoked"<<endl;}
-
};
-
-
typedef void (*fun)();
-
int main()
-
{
-
A a;
-
cout<<hex<<"(int) &a=0x"<<(unsigned int)(&a)<<endl;
-
cout<<hex<<"vtbl=0x"<<(unsigned int)*((unsigned int*)(&a))<<endl;
-
cout<<hex<<"vtbl::1stItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&a)) ))<<endl;
-
cout<<hex<<"vtbl::2ndItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&a))+1 ))<<endl;
-
cout<<hex<<"vtbl::3rdItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&a))+2 ))<<endl;
-
fun Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&a))));
-
Fun();
-
Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&a))+1));
-
Fun();
-
Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&a))+2));
-
Fun();
-
-
return 0;
-
}
运行输出:
2. 函数全体覆盖(override)后的情况:
-
#include <iostream>
-
using namespace std;
-
class A
-
{
-
public:
-
virtual void vFun1(){cout<<"vFun1() is invoked"<<endl;}
-
virtual void vFun2(){cout<<"VFun2() is invoked"<<endl;}
-
virtual void vFun3(){cout<<"vFun3() is invoked"<<endl;}
-
};
-
class B:public A
-
{
-
public:
-
void vFun1(){cout<<"B::vFun1() is invoked"<<endl;}
-
void vFun2(){cout<<"B::VFun2() is invoked"<<endl;}
-
void vFun3(){cout<<"B::vFun3() is invoked"<<endl;}
-
};
-
-
typedef void (*fun)();
-
int main()
-
{
-
B b;
-
cout<<hex<<"(int) &a=0x"<<(unsigned int)(&b)<<endl;
-
cout<<hex<<"vtbl=0x"<<(unsigned int)*((unsigned int*)(&b))<<endl;
-
cout<<hex<<"vtbl::1stItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&b)) ))<<endl;
-
cout<<hex<<"vtbl::2ndItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&b))+1 ))<<endl;
-
cout<<hex<<"vtbl::3rdItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&b))+2 ))<<endl;
-
fun Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))));
-
Fun();
-
Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))+1));
-
Fun();
-
Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))+2));
-
Fun();
-
-
return 0;
-
}
实例地址(实例中存放虚表地址):
虚表内容:
0x004112b2, 0x4112a3和0x4112a8参见前面QuickWatch图中定义。
3. 函数部分覆盖(override)后的情况:
子类函数针覆盖虚表中父类同名同参函数的指针项,因此调用实际所指对象的函数。
-
#include <iostream>
-
using namespace std;
-
class A
-
{
-
public:
-
virtual void vFun1(){cout<<"vFun1() is invoked"<<endl;}
-
virtual void vFun2(){cout<<"VFun2() is invoked"<<endl;}
-
virtual void vFun3(){cout<<"vFun3() is invoked"<<endl;}
-
};
-
class B:public A
-
{
-
public:
-
// void vFun1(){cout<<"B::vFun1() is invoked"<<endl;}
-
// void vFun2(){cout<<"B::VFun2() is invoked"<<endl;}
-
void vFun3(){cout<<"B::vFun3() is invoked"<<endl;}
-
virtual void vFun4(){cout<<"B::vFun4() is invoked"<<endl;}
-
};
-
-
typedef void (*fun)();
-
int main()
-
{
-
B b;
-
cout<<hex<<"(int) &a=0x"<<(unsigned int)(&b)<<endl;
-
cout<<hex<<"vtbl=0x"<<(unsigned int)*((unsigned int*)(&b))<<endl;
-
cout<<hex<<"vtbl::1stItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&b)) ))<<endl;
-
cout<<hex<<"vtbl::2ndItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&b))+1 ))<<endl;
-
cout<<hex<<"vtbl::3rdItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&b))+2 ))<<endl;
-
fun Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))));
-
Fun();
-
Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))+1));
-
Fun();
-
Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))+2));
-
Fun();
-
Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))+3));
-
Fun();
-
-
return 0;
-
}
多重继承情况
多重继承会有多个虚函数表,每个基类一个虚表。
子类函数指针将覆盖基类所有虚表中的同名同参函数指针。
子类中新增的虚函数将只增加到第一个虚函数表的后面。但不能用基类指针直接访问子类新增的虚函数,编译会报错,即使用函数指针访问也会出现crash。
阅读(3251) | 评论(1) | 转发(2) |