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到其他的父类的时候,需要做相应的指针的移动。

    三 完!

  • 相关阅读:
    HeadFirst学习笔记-1. 设计模式入门(转载)
    【译】StackExchange.Redis 中文文档目录(转载)
    Redis基础篇(一)数据类型与数据结构(转载)
    Redis基础(二)数据库(转载)
    Redis基础篇(八)数据分片(转载)
    Redis基础篇(七)哨兵机制(转载)
    Redis基础篇(六)数据同步:主从复制(转载)
    Python特点
    Python发展历史
    Python基础
  • 原文地址:https://www.cnblogs.com/sanghai/p/6525085.html
Copyright © 2011-2022 走看看