c++ 虚表
作者:互联网
1.虚表
C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。
虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。
C++的编译器应该是保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——如果有多层继承或是多重继承的情况下)。 这意味着我们通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。
2.虚表的布局
【1】一般继承,没有重写任何虚函数时:
虚函数按照其声明顺序放于表中,父类的虚函数在子类的虚函数前面。
【2】一般继承,有重写虚函数时:
覆盖的f()函数被放到了虚表中原来父类虚函数的位置,因此下面的程序中由b所指的内存中的虚函数表的f()的位置已经被Derive::f()函数地址所取代,于是在实际调用发生时,是Derive::f()被调用了。这就实现了多态。例如:
Base *b = new Derive(); b->f();
【3】多重继承,无虚函数覆盖时:
此时每个父类都有自己的虚表,子类的虚函数被放到了第一个父类的虚表中(所谓的第一个父类是按照声明顺序来判断的)。这样做就是解决了不同的父类类型的指针指向同一个子类实例,而能够调用到实际的函数。
【4】多重继承,有虚函数覆盖时:
此时三个父类虚函数表中的f()的位置被替换成了子类的函数指针。这样,我们就可以任一静态类型的父类来指向子类,并调用子类的f()了。如:
Derive d; Base1 *b1 = &d; Base2 *b2 = &d; Base3 *b3 = &d; b1->f(); //Derive::f() b2->f(); //Derive::f() b3->f(); //Derive::f() b1->g(); //Base1::g() b2->g(); //Base2::g() b3->g(); //Base3::g()
标签:Derive,虚表,函数,子类,c++,调用,父类 来源: https://www.cnblogs.com/iamwho/p/10528241.html