一 多重继承

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. laravel when 的用法

    当你在使用where语句有前提条件时,比如某值为1的时候才执行where子句,否则不执行,这个时候,laravel5.5新出了一个简便方法when($arg,fun1[,fun2]). 具体用法如下: ...

  2. excel中CTRL+E的用法

    偶然发现excel中CTRL+E有按照例子填充的功能. 结果如下

  3. python2.7入门---2.x与3​​.x版本区别

        Python的3​​.0版本,常被称为Python 3000,或简称Py3k.相对于Python的早期版本,这是一个较大的升级.为了不带入过多的累赘,Python 3.0在设计的时候没有考虑向 ...

  4. 20155315实验三 敏捷开发与XP实践

    实验内容 1.XP基础 2.XP核心实践 3.相关工具 实验要求 1.没有Linux基础的同学建议先学习<Linux基础入门(新版)><Vim编辑器> 课程: 2.完成实验.撰 ...

  5. 20155318 2016-2017-2 《Java程序设计》第三周学习总结

    20155318 2016-2017-2 <Java程序设计>第三周学习总结 教材学习内容总结 一.类与对象 Clothes c1 = new Clothes();将c1名称参考至新建对象 ...

  6. ruby学习笔记(2)-chomp,chop的区别

    还没开始系统性的学习Ruby,最近在看metasploit框架的exploit会涉及到Ruby脚本,也就硬着头皮一遍查阅资料一遍做些笔记吧. Ruby字符串中存在chop和chomp的内置函数.我在h ...

  7. day3 前奏

    1.第1个c语言 编辑---编译----运行 python@ubuntu:~/Desktop/pythons06$ vim -第1个c语言.c #include<stdio.h> int ...

  8. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言(内容已过期,阅读请慎重)

    2018-09-19 更新 :现在已经更新ASP.NET Core Middleware版本.对.NET Core SignalR感兴趣的朋友移步:https://github.com/fanpan2 ...

  9. cogs1713 [POJ2774]很长的信息

    cogs1713 [POJ2774]很长的信息 原题链接 题解 把两串拼成A+'%'+B+'$'.跑后缀数组然后相邻两点i,i+1不在同一串里就用ht[i]更新答案. 好裸... Code // It ...

  10. Angular开发者手册重点翻译之指令(一)

    创建自定义的指令 这个文章将解释什么需要在自己的angularjs应用中创建自己的指令,以及如何实现它. 什么是指令 在高的层面上讲,指令是DOM元素中的标记(例如一个属性,一个节点名,注释或者CSS ...