一 多重继承

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与对象内存布局
单继承与虚函数表 多重继承与虚函数表 虚继承与虚函数表
类型转化

C++对象模型 多重继承与虚函数表的更多相关文章

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

    转载: [C++对象模型][8]多重继承与虚函数表 一 多重继承 1) 代码: Code #include <iostream> using namespace std; class B1 ...

  2. C++ 虚函数表与多态 —— 多重继承的虚函数表 & 内存布局

    多重继承的虚函数表会有两个虚表指针,分别指向两个虚函数表,如下代码中的 vptr_s_1.vptr_s_2,Son类继承自 Father 和 Mather 类,并且改写了 Father::func_1 ...

  3. 详谈C++虚函数表那回事(多重继承关系)

    上一篇说了一般继承,也就是单继承的虚函数表,接下来说说多重继承的虚函数表: 1.无虚函数覆盖的多重继承: 代码: #pragma once //无覆盖,多重继承 class Base1 { publi ...

  4. C++ 虚函数表解析

    转载:陈皓 http://blog.csdn.net/haoel 前言 C++中 的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实 ...

  5. C++虚函数表原理

    C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指 向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有“多种形态”,这是一种泛型技 ...

  6. C++ 虚函数表解析(转载)

    转载自:陈皓 http://blog.csdn.net/haoel/article/details/1948051/ 前言 C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型 ...

  7. 转载:C++ 虚函数表解析

    目录(?)[+]   转载:http://blog.csdn.net/haoel/article/details/1948051# 前言 C++中 的虚函数的作用主要是实现了多态的机制.关于多态,简而 ...

  8. C++ 虚函数表解析(比较清楚,还可打印虚函数地址)

    C++ 虚函数表解析 陈皓 http://blog.csdn.net/haoel 前言 C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父 ...

  9. C++ 虚函数表决心

    C++ 虚函数表解析 xml:namespace prefix = o /> 陈皓 http://blog.csdn.net/haoel 前言 C++中的虚函数的作用主要是实现了多态的机制. 关 ...

随机推荐

  1. MAC下绕开百度网盘限速下载的方法,三步操作永久生效

    第一步:下载所需工具:(①②步我放在同一个文件夹,可一起下载,链接失效请留言) 工具地址:链接: https://pan.baidu.com/s/1raicYzM 密码: ve3n ①下载Aria2G ...

  2. 和IDEA一样好用的go语言IDE:Goland

    因为IDEA和Goland来自同一家非常有名的捷克公司:JetBrains 很好用,智能化程度高 最新版下载地址:http://www.jetbrains.com/go/?fromMenu 相关使用手 ...

  3. 学习笔记二:异步FIFO

      , ) //用格雷码的局限性:循环计数深度必须是2的n次幂,否则就失去了每次只变化一位的特性 (wclk,wrstn,wdata,wfull,winc,rclk,rrstn,rdata,rempt ...

  4. Binary Indexed Tree (Fenwick Tree)

    Binary Indexed Tree 主要是为了存储数组前缀或或后缀和,以便计算任意一段的和.其优势在于可以常数时间处理更新(如果不需要更新直接用一个数组存储所有前缀/后缀和即可).空间复杂度O(n ...

  5. week8课上实践

    课上练习. 第一题: 参考 http://www.cnblogs.com/rocedu/p/6766748.html#SECCLA 在Linux下完成"求命令行传入整数参数的和" ...

  6. 1111: [POI2007]四进制的天平Wag

    1111: [POI2007]四进制的天平Wag 链接 题意: 用一些四进制数,相减得到给定的数,四进制数的数量应该尽量少,满足最少的条件下,求方案数. 分析: 这道题拖了好久啊. 参考Claris的 ...

  7. 接口文档神器Swagger(下篇)

    本文来自网易云社区 作者:李哲 二.Swagger-springmvc原理解析 上面介绍了如何将springmvc和springboot与swagger结合,通过简单配置生成接口文档,以及介绍了swa ...

  8. zookeeper 简单小节

    1. ZooKeeper 是什么 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务.主要用来解决分布式集群中应用系统的一致性问题,它能提供基于类似于文件系统的目录节点树方式的数据存储 ...

  9. 安装Vue.js的方法有三种

    1 使用独立的版本 在Vue.js官网上直接下载,在script标签里引用. 2 使用CND方法(不推荐) 3 NMP 方法 在用Vue.js构建大型应用的时候推荐使用NMP安装方法,NMP能很好的和 ...

  10. python练习---小脚本

    一.爬子域名 #!/usr/bin/python # -*- coding: utf-8 -*- import requests import re import sys def get(domain ...