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

    一 多重继承

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

    三 完!

    感谢,Thanks!

    作者:iTech
    出处:http://itech.cnblogs.com/
    转载:本文版权归作者iTech所有,转载请注明出处,不得用于商业用途!

    C++对象模型系列:

    本系列是主要是作者经验的总结且同时参考了大量的网络文章,希望能够给C++的学习者有所帮助,但是由于作者水平有限,难免有错,希望大家能够指出,我将虚心地向大家学习,与大家共同进步!本系列的开发环境是Windows 32+VS2008。

    文章:

    指针和引用
    指针与数组
    指针与字符串
    堆栈与函数调用
    sizeof与对象内存布局
    单继承与虚函数表
    多重继承与虚函数表
    虚继承与虚函数表
    类型转化

  • 相关阅读:
    快速排序及其优化
    JVM基础:深入学习JVM堆与JVM栈(转)
    java 反射简介(转载)
    java 泛型简介(转载)
    Java 注解简介
    JVM入门必看——JVM结构
    Java多线程详解(转载)
    SpringMVC 实现文件的上传与下载
    死锁简介
    SQL的模糊查询(转载)
  • 原文地址:https://www.cnblogs.com/sideny/p/3301937.html
Copyright © 2011-2022 走看看