zoukankan      html  css  js  c++  java
  • [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
    ->= 10;
        pD
    ->= 20;
        pD
    ->= 30;
        pD
    ->= 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到其他的父类的时候,需要做相应的指针的移动。

    三 完!


    作者:iTech
    微信公众号: cicdops
    出处:http://itech.cnblogs.com/
    github:https://github.com/cicdops/cicdops

  • 相关阅读:
    Hibernate实体类注解
    Struts2注解详解
    Spring注解大全
    Maven依赖机制
    Maven启动代理服务器
    SSH整合
    二进制求和 —— 从复杂方法到简单方法
    最大子序和 —— 动态规划解法
    括号匹配问题 —— Deque双端队列解法
    常见面试题 —— 两数之和(拒绝暴利法)
  • 原文地址:https://www.cnblogs.com/itech/p/1399995.html
Copyright © 2011-2022 走看看