zoukankan      html  css  js  c++  java
  • 虚函数表,以及虚函数指针

    转自:http://www.cnblogs.com/Z465360621/articles/4561344.html

    1)每个有虚函数的类都有自己的虚函数表,每个包含虚函数的类对象都有虚函数表指针。

    2)对于多重继承,如果多个基类都有虚函数,则继承类中包含多个基类虚函数表,子类的虚函数地址放在声明的第一个基类虚函数表后面。

    3)计算类对象的内存大小的时候,需要计算有多少个虚函数指针。

    一般继承(无虚函数覆盖)

    假设有如下所示的一个继承关系:

    虚函数继承 - simple1110 - gino

    在这个继承关系中,子类没有重载任何父类的函数。那么,在派生类的实例中,其虚函数表如下所示:

    对于实例:Derive d; 的虚函数表如下:

    虚函数继承 - simple1110 - gino

    我们可以看到下面几点:

    1)虚函数按照其声明顺序放于表中。

    2)父类的虚函数在子类的虚函数前面。

    我相信聪明的你一定可以参考前面的那个程序,来编写一段程序来验证。

    一般继承(有虚函数覆盖)

    覆盖父类的虚函数是很显然的事情,不然,虚函数就变得毫无意义。下面,我们来看一下,如果子类中有虚函数重载了父类的虚函数,会是一个什么样子?假设,我们有下面这样的一个继承关系。

    虚函数继承 - simple1110 - gino

    为了让大家看到被继承过后的效果,在这个类的设计中,我只覆盖了父类的一个函数:f()。那么,对于派生类的实例,其虚函数表会是下面的一个样子:

    虚函数继承 - simple1110 - gino

    我们从表中可以看到下面几点,

    1)覆盖的f()函数被放到了虚表中原来父类虚函数的位置。

    2)没有被覆盖的函数依旧。

    这样,我们就可以看到对于下面这样的程序,

    Base *b = new Derive();

    b->f();

    由b所指的内存中的虚函数表的f()的位置已经被Derive::f()函数地址所取代,于是在实际调用发生时,是Derive::f()被调用了。这就实现了多态。

    多重继承(无虚函数覆盖)

    下面,再让我们来看看多重继承中的情况,假设有下面这样一个类的继承关系。注意:子类并没有覆盖父类的函数。

    虚函数继承 - simple1110 - gino

    对于子类实例中的虚函数表,是下面这个样子:

    虚函数继承 - simple1110 - gino

    我们可以看到:

    1) 每个父类都有自己的虚表。

    2) 子类的成员函数被放到了第一个父类的表中。(所谓的第一个父类是按照声明顺序来判断的)

    这样做就是为了解决不同的父类类型的指针指向同一个子类实例,而能够调用到实际的函数。

    多重继承(有虚函数覆盖)

    下面我们再来看看,如果发生虚函数覆盖的情况。

    下图中,我们在子类中覆盖了父类的f()函数。

    虚函数继承 - simple1110 - gino

    下面是对于子类实例中的虚函数表的图:

    虚函数继承 - simple1110 - gino

    我们可以看见,三个父类虚函数表中的f()的位置被替换成了子类的函数指针。

  • 相关阅读:
    POJ 1703 Find them, Catch them
    POJ 2236 Wireless Network
    POJ 2010 Moo University
    POJ 2184 Cow Exhibition
    POJ 3280 Cheapest Palindrome
    POJ 3009 Curling 2.0
    POJ 3669 Meteor Shower
    POJ 2718 Smallest Difference
    POJ 3187 Backward Digit Sums
    POJ 3050 Hopscotch
  • 原文地址:https://www.cnblogs.com/lpxblog/p/6558459.html
Copyright © 2011-2022 走看看