C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类类型的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。然后在运行时决定选用父类函数还是子类函数。
虚函数是通过一张虚函数表来实现的。虚函数表是一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,反应了类中虚函数的真实对应关系。
C++的编译器保证虚函数表的指针存在于对象实例中最前面的位置,这是为了保证取到虚函数表的有最高的性能。这意味着我们通过对象实例的地址得到虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。关于这些,下面有个清晰的说明。
定义Base和Derive:
class Base
{
public:
virtual void func1()
{
cout<<"base1()"<<endl;
}
virtual void func2()
{
cout<<"base2()"<<endl;
}
};
class Derive : public Base
{
public:
virtual void func1()
{
cout<<"derive1()"<<endl;
}
};
int main()
{
//定义函数指针Fun
typedef void(*Function)(void);
//定义Base对象
Base base;
Function pFunction = NULL;
//验证虚函数表的指针存在于对象实例中最前面的位置
pFunction = (Function)*((int*)*(int*)(&base));
pFunction();//输出base1(),即pFunction为func1(),说明了虚函数表的指针存在于对象实例中最前面的位置.
//同理
pFunction = (Function)*((int *)*(int *)(&base)+1);
pFunction();//输出base2();
//同样的方法访问derive中的函数
Derive derive;
int** pVtab = (int**)&derive;
pFunction = (Function)pVtab[0][0];
pFunction();//由于被子类func1覆盖,输出derive1();
pFunction = (Function)pVtab[0][1];
pFunction();//输出base2();
return 0;
}
虚函数表:

下面介绍下多重继承。
无覆盖:

子类实例中的虚函数表:

1)每个父类都有自己的虚表。
2)子类的成员函数被放到了第一个父类的表中。(所谓的第一个父类是按照声明顺序来判断的)
有覆盖:
在子类中覆盖了父类的f()函数
子类实例中的虚函数表:

一些特别的说明:
通过父类型的指针访问子类自己的虚函数
在正上方这个图中,我们无法这样访问g1:
Base1 *b1 = new Derive();
b1->g1(); //编译出错
但是我们可以采用下面的方法,通过指针的方式访问虚函数。
Base *b = new Derive();
pFunction = (Function)*((int *)*(int *)(b) + 1);
pFunction();//Derive:g1();
通过子类类型的指针访问父类自己的私有虚函数
class Base {
private:
virtual void f()
{
cout<< "Base::f" << endl;
}
};
class Derive : public Base
{
};
调用
Derive d;
Function pFunction = (Function)*((int*)*(int*)(&d)+0);
pFunction();
参考自http://blog.csdn.net/liufei_learning/article/details/5443282
posted on 2012-01-14 12:34
HiHi..! 阅读(90)
评论(0) 编辑 收藏 引用 所属分类:
c++