`
mmdev
  • 浏览: 12845795 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

【C++面向对象】类的大小以及虚继承

 
阅读更多

先看下面一段代码:


运行于VS2008上的结果是:


为什么会出现这样的结果?下面来进行分析。

先看看上述程序中类的继承关系:


我们先看类X。X类明明是空的,为什么sizeof(X) = 1呢?

原因是因为事实上X并不是空的,它有一个隐晦的1字节,那是编译器安插进去的一个char。这会是的class X的两个objects得以在内存中配置独一无二的地址。

class Y和Z的结果同样令人不解。


事实上Y和Z的大小受到三个因素的影响:

(1)语言本身所造成的额外负担。当语言支持虚基类(virtual base classes)时,就会造成一些额外负担。在子类中,这个额外负担反映在某种形式的指针身上,或者指向虚基类子对象,或者指向一个相关的表格;表格中存放的不是虚基类子对象的地址,就是其偏移量。

(2)编译器对于特殊情况所做的优化处理。虚基类子对象的1字节大小也出现在Y和Z中。传统上放在子类对象的尾端。

现在的编译器一般会对空虚基类提供特殊支持(比如VS2008)。在这个策略下,一个空虚基类被视为子类对象最开头的一部分,也就是说它并没有花费任何的额外空间。这就节省了前述的1字节。(因为既然有了成员,就不需要原本为了空类而安插的1个char)。

(3)Alignment的限制。就是字节对齐,具体可参考:字节对齐详解。在这里没有增加额外的空间。


因此,Y和Z的大小都是4字节。


下面我们讨论A的大小。

这里需要注意的是:一个虚基类子对象只会在继承类中存在一份实体,不管它在继承体系中出现了多少次!!!


A类大小由以下几点决定:

(1)被共享的X类实体,大小为1字节。

(2)Y的大小,需要减去因为虚基类X而配置的大小。4字节。

(3)A自己的大小:0字节。

(4)A字节对齐作用产生的额外空间。

结果是12字节。


注意:C++标准并不强制规定如“基类子对象的排列次序”或不同存取层级的数据成员的排列次序这种琐碎细节。也不规定虚函数和虚基类的实现细节。

分享到:
评论

相关推荐

    C++ Primer第四版【中文高清扫描版】.pdf

    第四部分 面向对象编程与泛型编程 第15章 面向对象编程 471 15.1 面向对象编程:概述 472 15.2 定义基类和派生类 473 15.2.1 定义基类 474 15.2.2 protected成员 475 15.2.3 派生类 476 15.2.4 virtual与其他成员...

    上课时的练习代码主要为C语言代码,部分C++.rar

    C++是面向对象的语言,主要特征是“封装、继承和多态”。封装隐藏了实现细节,使得代码模块化;派生类可以继承父类的数据和方法,扩展了已经存在的模块,实现了代码重用;多态则是“一个接口,多种实现”,通过派生...

    C++ Primer中文版(第5版)李普曼 等著 pdf 1/3

     15.9.1 面向对象的解决方案 563  15.9.2 Query_base类和Query类 567  15.9.3 派生类 568  15.9.4 eval函数 571  小结 575  术语表 575  第16章 模板与泛型编程 577  16.1 定义模板 578  16.1.1 函数模板 ...

    C++Primer(第5版 )中文版(美)李普曼等著.part2.rar

     15.9.1 面向对象的解决方案 563  15.9.2 Query_base类和Query类 567  15.9.3 派生类 568  15.9.4 eval函数 571  小结 575  术语表 575  第16章 模板与泛型编程 577  16.1 定义模板 578  16.1.1 函数模板 ...

    Visual C++ 2005入门经典.part08.rar (整理并添加所有书签)

    9.1 面向对象编程的基本思想 9.2 类的继承 9.2.1 基类的概念 9.2.2 基类的派生类 9.3 继承机制下的访问控制 9.3.1 派生类中构造函数的操作 9.3.2 声明类的保护成员 9.3.3 继承类成员的访问级别 9.4 派生类中的复制...

    Visual C++ 2005入门经典.part04.rar (整理并添加所有书签)

    9.1 面向对象编程的基本思想 9.2 类的继承 9.2.1 基类的概念 9.2.2 基类的派生类 9.3 继承机制下的访问控制 9.3.1 派生类中构造函数的操作 9.3.2 声明类的保护成员 9.3.3 继承类成员的访问级别 9.4 派生类中的复制...

    Visual C++实践与提高-COM和COM+篇『PDF』

    1.1.3 面向对象程序设计方法 1.1.4 最终解决方案:组件软件 1.1.5 面向对象的组件模型——COM 1.2 COM的发展历程 1.2.1 COM以前的对象技术:DDE、OLE 1、VBX控件 1.2.2 COM首次亮相:OLE2 1.2.3 Microsoft拥抱...

    C++数据抽象和问题求解(第6版).[美]Frank M. Carrano(带详细书签).pdf

    这本经典、畅销的数据结构教材详细介绍了数据抽象的基础知识,强调作为面向对象方法基础原理的规范和实施之间的区别。书中使用的软件工程原则和概念以及UML图便于增强学生的理解。 ◆ 详细介绍了数据抽象,强调规范...

    Visual C++ 2005入门经典.part05.rar (整理并添加所有书签)

    9.1 面向对象编程的基本思想 9.2 类的继承 9.2.1 基类的概念 9.2.2 基类的派生类 9.3 继承机制下的访问控制 9.3.1 派生类中构造函数的操作 9.3.2 声明类的保护成员 9.3.3 继承类成员的访问级别 9.4 派生类中的复制...

    C++编程思想.pdf

    内容涉及对象的演化、数据抽象、隐藏实现、初始化与清除、函数重载与缺省参数、输入输出流介绍、常量、内联函数、命名控制、引用和拷贝构造函数、运算符重载、动态对象创建、继承和组合、多态和虚函数、模板和包容器...

    aybook.cn_c++jiaocheng0105.rar

    8.2 引用参数 8.3 函数的重载 8.4 函数的默认函数 8.5 函数重载与歧义性 第9章 更多的数据类型与运算符 第10章 结构与联合 第11章 类 第12章 类的深入学习 第13章 运算符的重载 第14章 继承 第15章 虚函数与多态 第...

    C++课程设计高校水电管理系统+课程报告

    通过写高校水电管理系统,使我们更好的掌握C++语言,同时更好的掌握面向对象的设计思想。提高学生自我分析问题,解决问题的能力。 研究的内容和方法 : 本程序通过写文件,将信息从客户终端写入到文件中并保存。在...

    Visual C++ 2005入门经典--源代码及课后练习答案

    9.1 面向对象编程的基本思想 440 9.2 类的继承 441 9.2.1 基类的概念 442 9.2.2 基类的派生类 442 9.3 继承机制下的访问控制 446 9.3.1 派生类中构造函数的操作 448 9.3.2 声明类的保护成员 452 ...

    Visual C++ 2010入门经典(第5版)--源代码及课后练习答案

    7.2 数据类型、对象、类和实例 301 7.2.1 类的起源 303 7.2.2 类的操作 303 7.2.3 术语 303 7.3 理解类 304 7.3.1 定义类 304 7.3.2 声明类的对象 305 7.3.3 访问类的数据成员 305 7.3.4 类的成员函数 307 ...

    Visual C++ 2005入门经典.part07.rar (整理并添加所有书签)

    9.1 面向对象编程的基本思想 9.2 类的继承 9.2.1 基类的概念 9.2.2 基类的派生类 9.3 继承机制下的访问控制 9.3.1 派生类中构造函数的操作 9.3.2 声明类的保护成员 9.3.3 继承类成员的访问级别 9.4 派生类中的复制...

    Visual C++ 2005入门经典.part09.rar (整理并添加所有书签)

    9.1 面向对象编程的基本思想 9.2 类的继承 9.2.1 基类的概念 9.2.2 基类的派生类 9.3 继承机制下的访问控制 9.3.1 派生类中构造函数的操作 9.3.2 声明类的保护成员 9.3.3 继承类成员的访问级别 9.4 派生类中的复制...

    Visual C++ 2005入门经典.part06.rar (整理并添加所有书签)

    9.1 面向对象编程的基本思想 9.2 类的继承 9.2.1 基类的概念 9.2.2 基类的派生类 9.3 继承机制下的访问控制 9.3.1 派生类中构造函数的操作 9.3.2 声明类的保护成员 9.3.3 继承类成员的访问级别 9.4 派生类中的复制...

Global site tag (gtag.js) - Google Analytics