一、单继承

class A {int a;};
class B : public A {int b;};

普通的单继承关系,类的大小是由其虚表指针和非静态成员函数大小决定。故上述sizeof(A)的大小为4。

类B公有继承A,对象模型如下:

  类A的非静态成员(4字节)

  类B的非静态成员(4字节)

故类B的大小为8字节。

二、多继承

class A {int a;};
class B {int b;};
class C : public A, public B {int c;};

普通的多继承关系,这里和上述单继承类似。直接给出类C的对象模型如下:

  类A的非静态成员(4字节)

  类B的非静态成员(4字节)

  类C的非静态成员(4字节)

故类C的大小为12字节。

三、含有虚函数的普通继承

(1)含有虚函数的类对象模型

C++中引入了虚函数,即多态的概念。如果一个类中存在虚函数,则该类对象在被实例化时,其首地址开始的4个字节存放着虚函数表指针(vptr),vptr指向了一个虚表(理解为结构体数组),数组中的每一个位置存放着虚函数的实际地址。(ps:一个类的大小与其非成员变量有关,所以如果一个仅包含虚函数的类,其大小只有一个虚表指针,即4字节)

class A
{
virtual void test(void);
int a;
};

故上述类A的大小为,一个vptr加上一个成员变量,为8字节。

(2)含有虚函数的普通单继承

class A
{
virtual void test(void);
int a;
}; class B : public A
{
int b;
};

类B直接继承类A,由于类A中存在虚函数,所以类B对象中同样也会有vptr虚表指针,并指向一个虚表,用于重写test函数。类B的对象模型如下:

  类B的vptr(4字节)  ----->  指向了一个虚表

  类A的非静态成员(4字节)

  类B的非静态成员(4字节)

故类B的大小为12字节。(先虚表,然后是基类的成员,最后是子类的成员)

(3)含有虚函数的多继承

含有虚函数的多继承

class A
{
virtual void test_a(void){}
int a;
}; class B
{
virtual void test_b(void){}
int b;
}; class C : public A, public B {int c;};

类C的对象模型如下:

  类A的vptr

  A::a

  类B的vptr

  B::b

  C::c

四、含有虚函数的类对象虚继承

class A
{
virtual void test(void);
int a;
}; class B : public virtual A
{
   void test(void);
  virtual void test1(void);
int b;
};

直接给出类B的对象模型如下:

  类B的vptr(4字节)    ----->  指向虚表,新增的虚函数放在自己的虚表

  类B的非静态成员(4字节)

  类A的vptr(4字节)              ------>  指向虚表,重写的虚函数放在这个虚表。保存B::test()

  类A的非静态成员(4字节)

故类B的大小为16字节。

五、菱形继承

所谓菱形继承,是一种较为特殊的多继承关系,融合了多继承与虚继承。如图:

结合代码如下:

class X {};
class Y : public virtual X {};
class Z : public virtual X {};
class A : public Y, public Z {};

如果通过sizeof输出上述四个类的大小,结果为:1,4,4,8。

(1)、空类的大小

C++定义一个类如果是一个空类,会被编译器默认插入一个char(1个字节),从而使得该类的两个对象在内存中可以有独一无二的地址。所以上述sizeof(X)结果为1

(2)、虚继承类的大小

在虚继承的子类中,子类除了vptr,还会增加一种形式的指针。这个指针或者指向虚基类子对象,或者指向一个相关的表格,表格中存放的不是虚基类子对象的地址,就是其偏移量,这个指针被称为bptr。(在同时存在vptr和bptr的时候,某些编译器会将其优化,合并为一个指针)

故上述Y和Z,自身包含指针bptr(占四个字节),继承X的非静态成员变量(占0个字节),故sizeof(Y)和sizeof(Z)结果都为4。

(3)、类A的大小

A是直接从Y和Z多继承而来,由于X是一个虚基类(子类都虚继承),所以在A中仅仅会存在一个X类的副本。整个A的对象结构为:

  类Y的bptr(4字节)    

  类Y的非静态成员(0字节)  

  类Z的bptr(4字节)

  类Z的非静态成员(0字节)

  类A的非静态成员(0字节)

  类X的非静态成员(0字节)

故sizeof(X)结果为8。这里从上往下分别是Y和Z的顺序,是由类A的继承顺序决定的。

参考:https://www.cnblogs.com/fanzhidongyzby/archive/2013/01/14/2859064.html

C++学习之路(九):从菱形继承引入的对象模型的更多相关文章

  1. 【jq】c#零基础学习之路(3)继承和虚方法

    c#只能继承一个基类和多个接口(0+) 父类:Human: class Human { public virtual Move() { Console.WriteLine("Human的虚方 ...

  2. Android开发学习之路-自定义ListView(继承BaseAdapter)

    大三学生一个,喜欢编程,喜欢谷歌,喜欢Android,所以选择的方向自然是Android应用开发,开博第一篇,希望以后会有更多的进步. 最近在做一个记账App的时候,需要一个Activity来显示每个 ...

  3. zigbee学习之路(九):串口(发送)

    一.前言 今天,我们来学习和实验串口模块方面的,串口通信是我们常用的通信手段,通过串口交互,我们可以很容易的和pc机进行数据的交换和发送,所以我们今天就来学习一下.这个实验所进行的功能是一开始CC25 ...

  4. 嵌入式Linux驱动学习之路(九)Linux系统调用、驱动程序框架

    应用程序通过open  read  write close 等函数来操作计算机硬件.类似是一个接口. 当应用程序调用这些接口程序时,计算机是如何进入内核的呢?这是经过了系统调用. 实际上当调用接口函数 ...

  5. Object-c学习之路九(字典(NSDictionary&NSMutableDictionary))

    字典的练习和使用(遍历,搜索...)(Student和Book类文件可以查看上篇博客这次不上传了.) // // main.m // NSDictionary // // Created by Wil ...

  6. IOS7学习之路九(ios7自定义UIAlertView)

    IOS7的UIAlertView 不支持自定义,无法添加subview . 不过可以用第三方库git上的下载链接    https://github.com/wimagguc/ios-custom-a ...

  7. IOS学习之路九(配置restful webservice 框架restkit)

    RestKit 是一个开源的 objective-c 框架,容许在 iOS 和 Mac OS X 的 Objective-C 中与 RESTful Web 办事进行交互,包含简单的 HTTP requ ...

  8. Java学习之路(九):Map集合

    Map集合概述和特点 Map是属于java.util的一个接口Map<k,v> k:映射所维护的键的类型 v:映射值的类型 Map是将键映射到值的对象.一个映射不能包含重复的键:每个键最多 ...

  9. Qt 学习之路 2(10):对象模型

    Home / Qt 学习之路 2 / Qt 学习之路 2(10):对象模型 Qt 学习之路 2(10):对象模型  豆子  2012年9月2日  Qt 学习之路 2  45条评论 标准 C++ 对象模 ...

随机推荐

  1. 第198天:js---内置对象的原型链和其他知识

    一.内置对象的原型链 1.Object原型 function test() {} alert(test.toString()); //新增属性 Object.prototype.mytest = fu ...

  2. 第109天:Ajax请求GET和POST的区别

    一.Ajax请求GET和POST的区别 1.使用Get请求时,参数在URL中显示,而使用Post方式,则不会显示出来 2.使用Get请求发送数据量小,Post请求发送数据量大 3.get请求需注意缓存 ...

  3. 第100天:CSS3中animation动画详解

    CSS3属性中有关于制作动画的三个属性:Transform,Transition,Animation: 一.Animation定义动画 CSS3的Animation是由“keyframes”这个属性来 ...

  4. HttpWebRequest和HttpWebResponse的应用

    创建使用类HttpHelper: public class Httpparam { public string UserAgent { get; set; } public string Accept ...

  5. 【Python】Python网络编程

    python内置封装了很多常见的网络协议的库,因此python成为了一个强大的网络编程工具,这里是对python的网络方面编程的一个简单描述. urllib 和 urllib2模块 urllib 和u ...

  6. 【bzoj3573】[HNOI2014]米特运输 树形dp

    题目描述 米特是D星球上一种非常神秘的物质,蕴含着巨大的能量.在以米特为主要能源的D星上,这种米特能源的运输和储存一直是一个大问题.D星上有N个城市,我们将其顺序编号为1到N,1号城市为首都.这N个城 ...

  7. (转)Spring用代码来读取properties文件

    转至http://www.cnblogs.com/Gyoung/p/5507063.html 我们都知道,Spring可以@Value的方式读取properties中的值,只需要在配置文件中配置org ...

  8. 吉哥系列故事――完美队形II HDU - 4513(马拉车变一下形)

    题意: 求最长回文串...但这个回文串要符合从中间到两头 逐个递减 解析: 在扩散的时候加一个判断就好了 #include <iostream> #include <cstdio&g ...

  9. [HNOI2006]最短母串问题 AC自动机

    题面:洛谷 题解: 如果我们对这些小串建出AC自动机,那么我们所求的大串就是要求满足遍历过所有AC自动机上的叶子节点,且经过步数最少的串.如果有多个步数相同的串,要输出字典序最小的串. 在AC自动机上 ...

  10. Netsh命令-网络禁用开启

    禁用无线网卡:netsh interface set interface wlan0 disabled 启用无线网卡:netsh interface set interface wlan0 enabl ...