zoukankan      html  css  js  c++  java
  • [C++对象模型][8]多重继承与虚函数表

    转载:

    [C++对象模型][8]多重继承与虚函数表

    一 多重继承

    1) 代码:

    Code
    #include <iostream>
    using namespace std;
    
    class B1
    {
    public:
        int x;
        virtual void v1(){ cout << "B1::v1" << endl; }
        void f1(){cout << "B1::f1" << endl; }
    };
    
    class B2
    {
    public:
        int y;
        virtual void v2(){ cout << "B2::v2" << endl; }
        void f2(){ cout << "B2::f2" << endl; }
    };
    
    class B3
    {
    public:
        int z;
        virtual void v3(){ cout << "B3::v3" << endl; }
        void f3(){ cout << "B3::f3" << endl; }
    };
    
    class D : public B1, public B2, public B3
    {
    public:
        int a;
        void v3(){ cout << "D::v3" << endl; }
        virtual void vD(){ cout << "D::vD" << endl; }
    };
    

      2)类图:

    3)VS2008的编译选项查看布局:

    4)可视化表示:

    5)代码验证:

    Code
    typedef void (*Fun)();
    
    void PrintMember(int *pI)
    {
        cout << *pI << endl;
    }
    void PrintVT(int *pVT)
    {
        while(*pVT != NULL)
        {
            (*(Fun*)(pVT))();
            pVT++;
        }
    }
    
    void PrintVTAndMember(B1 *pD)
    {
        int *pRoot = (int*)pD;
        int *pVTB1 = (int*)*(pRoot + 0);PrintVT(pVTB1);
        int *pMB1 = pRoot +1; PrintMember(pMB1);
        int *pVTB2 = (int*)*(pRoot + 2);PrintVT(pVTB2);
        int *pMB2 = pRoot +3; PrintMember(pMB2);
        int *pVTB3 = (int*)*(pRoot + 4);PrintVT(pVTB3);
        int *pMB3 = pRoot +5; PrintMember(pMB3);
    }
    
    void TestVT()
    {
        B1 *pB1 = new D();
        D *pD = dynamic_cast<D*>(pB1);
        pD->x = 10;
        pD->y = 20;
        pD->z = 30;
        pD->a = 40;
        PrintVTAndMember(pD);
        delete pD;
    }
    

      6) 验证代码运行结果:

    7)总结:

    与单继承相同的是所有的虚函数都包含在虚函数表中,所不同的多重继承有多个虚函数表,当子类对父类的虚函数有重写时,子类的函数覆盖父类的函数在对应的虚函数位置,当子类有新的虚函数时,这些虚函数被加在第一个虚函数表的后面。

    二 多重继承运行时类型转化

    1)代码验证:

    Code
    void TestDynamicCast()
    {
        B1 *pB1 = new D();
        cout << "B1:" << pB1 << endl;
        D *pD = dynamic_cast<D*>(pB1);
        cout << "D:"<< pD << endl;
        B2 *pB2 = dynamic_cast<B2*>(pB1);
        cout << "B2:" << pB2 << endl;
        B3 *pB3 = dynamic_cast<B3*>(pB1);
        cout << "B3:" << pB3 << endl;
        delete pD;
    }
    

      2)验证代码的运行结果:

    3)总结:

    从多重继承的内存布局,我们可以看到子类新加入的虚函数被加到了第一个基类的虚函数表,所以当dynamic_cast的时候,子类和第一个基类的地址相同,不需要移动指针,但是当dynamic_cast到其他的父类的时候,需要做相应的指针的移动。

    三 完!

  • 相关阅读:
    bzoj2733 永无乡 平衡树按秩合并
    bzoj2752 高速公路 线段树
    bzoj1052 覆盖问题 二分答案 dfs
    bzoj1584 打扫卫生 dp
    bzoj1854 游戏 二分图
    bzoj3316 JC loves Mkk 二分答案 单调队列
    bzoj3643 Phi的反函数 数学 搜索
    有一种恐怖,叫大爆搜
    BZOJ3566 概率充电器 概率dp
    一些奇奇怪怪的过题思路
  • 原文地址:https://www.cnblogs.com/sanghai/p/6525085.html
Copyright © 2011-2022 走看看