• C++对象内存模型2 (虚函数,虚指针,虚函数表)


    从例子入手,考察如下带有虚函数的类的对象内存模型:

     1 class A {
     2 public:
     3     virtual void vfunc1();
     4     virtual void vfunc2();
     5     void func1();
     6     void func2();
     7     virtual ~A();
     8 private:
     9     int m_data1, m_data2;
    10 }; 
    11 
    12 class B : A {
    13 public:
    14     virtual void vfunc1();;
    15     void func2();
    16     virtual ~B();
    17 private:
    18     int m_data3;
    19 };
    20 
    21 class C : B {
    22 public:
    23     virtual void vfunc1();
    24     void func();
    25 private:
    26     int m_data1, m_data4;
    27 };

    注:在子类中出现与父类相同名称的变量和非虚函数不是最佳实践,这里是为了说明其内存结构。

    其对象内存结构见下图。

                                                   *图片来源于侯捷老师

    对其分析如下:

    1. 每个含有虚函数的类在内存中多一根指针(vptr),见图中a,b,c对象中第一个位置,存储的是虚函数表(vtbl)所在的位置。

    2. 虚函数表(vtbl)存储着所有虚函数的位置,由于其动态绑定特性,在覆写(override)后在子类中存储的虚函数位置与父类中不相同。

    3. 分析上述代码, B继承A,所以A中的数据部分也被B继承下来,同时B添加上了自己的数据部分m_data3,加之vptr,组成了B左侧的内存布局。

      A中的虚函数vfunc1(),vfunc2()可以被覆写和动态绑定。

      所以在B中,vfunc1()被覆写,其vtbl中对应项指向了新的函数的位置(亮蓝色)。vfunc2()未被覆写,仍然指向原先位置(深蓝色)。

      C与B同理,vfunc1()被覆写,其vtbl中对应项指向了新的函数的位置(橘黄色)。vfunc2()未被覆写,仍然指向原先位置(深蓝色)。

    非虚函数静态绑定,存储在单独的内存空间(code memory section,灰色函数部分),调用时把对象的this指针,传给一个invisible参数,以便确定谁在调用函数。

    4. 调用虚函数的语句的C语言形式如图中下部分所示,其中n表示对应的函数在第几个位置(编译器在建立虚函数表的时候已知),从而实现动态绑定。

  • 相关阅读:
    JQuery empty方法和remove方法的区别,使用remove清除之前的文本内容??
    乙_1023 组个最小数 (20分)
    乙_1022 D进制的A+B (20分)
    乙_1021 个位数统计 (15分)
    乙_1020 月饼 (25分)
    乙_1013 数素数 (20分)
    乙_1009 说反话 (20分)
    乙_1008 数组元素循环右移问题 (20分)
    乙_1007 素数对猜想 (20分)
    乙_1005 继续(3n+1)猜想 (25分)
  • 原文地址:https://www.cnblogs.com/wangxiaobao/p/5850949.html
Copyright © 2020-2023  润新知