《深度探索C++对象模型》读书笔记(3)

在visual C++ 6.0中测试如下代码:

#include "iostream"
using namespace std;

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

int main()
{
    cout<<"sizeof(X): "<<sizeof(X)<<endl;
    cout<<"sizeof(Y): "<<sizeof(Y)<<endl;
    cout<<"sizeof(Z): "<<sizeof(Z)<<endl;
    cout<<"sizeof(A): "<<sizeof(A)<<endl;

    return 0;
}

得出的结果也许会令你毫无头绪

sizeof(X): 1
sizeof (Y): 4
sizeof(Z): 4
sizeof(A): 8

下面一一阐释原因:

(1)对于 一个class X这样的空的class,由于需要使得这个class的两个objects得以在内存中配置独一无二的地 址,故编译器会在其中安插进一个char.因而class X的大小为1.

(2)由于class Y虚拟继承于 class X,而在derived class中,会包含指向visual base class subobject的指针(4 bytes),而由 于需要区分这个class的不同对象,因而virtual base class X subobject的1 bytes也出现在class Y中 (1 bytes),此外由于Alignment的限制,class Y必须填补3bytes(3 bytes),这样一来,class Y的 大小为8.

需要注意的是,由于Empty virtual base class已经成为C++ OO设计的一个特有术语, 它提供一个virtual interface,没有定义任何数据。visual C++ 6.0的编译器将一个empty virtual base class视为derived class object最开头的一部分,因而省去了其后的1 bytes,自然也不存在后面 Alignment的问题,故实际的执行结果为4.

(3)不管它在class继承体系中出现了多少次,一个 virtual base class subobject只会在derived class中存在一份实体。因此,class A的大小有以下几 点决定:(a)被大家共享的唯一一个class X实体(1 byte);(b)Base class Y的大小,减去 “因virtual base class X而配置”的大小,结果是4 bytes.Base class Z的算法亦同。 (8bytes)(c)classs A的alignment数量,前述总和为9 bytes,需要填补3 bytes,结果是12 bytes.

考虑到visual C++ 6.0对empty virtual base class所做的处理,class X实体的那1 byte将被拿掉,于是额外的3 bytes填补额也不必了,故实际的执行结果为8.

不管是自身class的 还是继承于virtual或nonvirtual base class的nonstatic data members,其都是直接存放在每个class object之中的。至于static data members,则被放置在程序的一个global data segment中,不会影响 个别的class object的大小,并永远只存在一份实体。

***Data Member的绑定***

早期 C++的两种防御性程序设计风格的由来:

(1)把所有的data members放在class声明起头处,以 确保正确的绑定:

class Point3d
{
// 在class声明起头处先放置所有的data member
float x,y,z;
public:
float X() const { return x; }
// ...
};

时间: 2024-11-08 17:14:09

《深度探索C++对象模型》读书笔记(3)的相关文章

深度探索C++对象模型(3)

介绍 多态是一种威力强大的设计机制,允许你继承一个抽象的public接口之后,封装相关的类型,需要付出的代价就是额外的间接性--不论是在内存的获得,或是在类的决断上,C++通过class的pointer和references来支持多态,这种程序风格就称为"面向对象". 大家好,雷神关于<深度探索C++对象模型>笔记终于又和大家见面了,速度慢的真是可以.好了不浪费时间了,直接进入主题. 这篇笔记主要解决了几个常常被人问到的问题. 1.C++支持多重继承吗? 2.结构和类的区别

《深度探索C++对象模型》读书笔记 最后一记

第6章主要讲述了执行期语意学,主要内容是关于数组的在构建和析构是如何进行的. 第7章主要讲述了有关Template的相关内容. 这两章内容散见于<Effective C++>.<More Effective C++>.<C++Primer><C++Templates中 文版>等书籍,如果感兴趣请阅读对应的书籍. 本读书笔记主要想谈一下对语意的理解. 本人认为C++程序设计可以简单分为三个层次:语法层.语言语意层(就像<深度探索C++对象模型>所讲

《深度探索C++对象模型(Inside The C++ Object Model )》学习笔记

来源:http://dsqiu.iteye.com/blog/1669614 之前一直对C++内部的原理的完全空白,然后找到<Inside The C++ Object Model>这本书看了下, 感觉收获很大,因为书写得比较早,有些知识应该要更新,但是还是值得好好研读,由于该书的内容给人比较散的感觉,所以一直想找个时间整理一下,遂成此文,虽然都是抄书上的,但是却让我有了温故而知新的觉悟,附近里有三个好资料,一并共享了!2012年9月2日凌晨 4:31 谢谢 张雨生的歌声的相伴!   <

深度探索C++对象模型(7)

关于<深度探索C++对象模型>停顿了半个月,今天继续啃这个骨头,我的学习进入了第四章,函数的语意学.先做个复习C++支持三种成员函数:静态.虚.和非静态.每一种函数的调用方式都不同,当然他们的作用也会有区别,一般来说我们只要掌握根据我们的需要正确的使用这三种类型的成员函数便可以了,至于内部是如何运做的我们可以不知.但是<深度探索C++对象模型>正是让我们对这些不知道的东西进行深度探索的一本书.通过前面的学习,我想我知道了一些以前不知道的东西,但是感觉并没有提高多少,也许是我对此书的

深度探索C++对象模型(2)

史列因:我刚看了你写的"深度探索C++对象模型(1)",感觉很不错.不过我有一个建议:你说"谁知第一章便如此的难以消化,已经反复读了3遍,还是有些夹生"是很自然的.第一章是一个总览,如果你能全看懂,后面的就没什么看的必要了.第一章的内容后面都有详细介绍,开始只要有个大概印象就可以了.这本书中很多内容都是前后重复的.我建议你先不管看懂看不懂,只管向后看,之后再从头看几遍,那样效果好得多. 我想史列因说的应该是一种非常好的阅读方式,类似<深度探索C++对象模型&g

深度探索C++对象模型(4)

雷神跌跌撞撞的读完了<深度探索C++对象模型>的第一章,虽然还是有些疑惑,但是已经感到收获很大.按照朋友的说法,第一章是一个概括的介绍,具体的细节会在以后的章节阐述,如果没有通读本书,第一章还是比较不容易理解的.雷神听过之后信心倍增,也不在有初看此书时的"世界末日"的感觉了(在第2篇雷神感到学了近一年的C++,居然水平如此之差),并且通过自己的努力,还是摸到了些门道,所以让我们继续快乐的出发,踏上深度探索C++对象模型的旅程.记住我们在第一篇的小文<坚持不懈,直到成功

c++-深度探索C++对象模型 虚函数表指针问题

问题描述 深度探索C++对象模型 虚函数表指针问题 <深度探索C++对象模型>中文版116页, "某些编译器设计了一种优化技术,只要第二个(或后继)base class声明了一个virtual function,而第一个base class没有,就把多个base classes的顺序调换.这样可以在derived class object中少产生一个vptr" vptr是如何减少的,想不明白,跪求解答 解决方案 没有虚函数的基类就不需要vptr了 解决方案二: 这个涉及虚表

《深度探索C++对象模型》读书笔记(1)

在C++中,有两种class data members:static和nonstatic,以及三种class member functions: static.nonstatic和virtual.已知下面这个class Point声明: class Point ...{ public: Point(float xval); virtual ~Point(); float x() const; static int PointCount(); protected: virtual ostream&

《深度探索C++对象模型》读书笔记(7)

***Template的"具现"行为*** template class中的任何member都只能通过template class的某个实体来存取或操作. Point<float>::Status s; // ok Point::Status s; // error 如果我们定义一个指针,指向特定的实体,像这样: Point<float> *ptr = 0; 由于这是一个指向class object的指针,本身并不是一个class object,编译器不需要知道

《深度探索C++对象模型》读书笔记(6)

***对象的构造和解构*** 一般而言,我们会把object尽可能放置在使用它的那个程序区段附近,这样做可以节省不必要的对象 产生操作和销毁操作. ***全局对象*** 全局对象的静态初始化策略包括以下几个步骤: (1)为每一个需要静态初始化的对象产生一个_sti_--()函数,内含必要的 constructor调用操作或inline expansions: (2)为每一个需要静态的内存释放操作的对象产生一个_std_--()函数,内含必要 的destructor调用操作或inline expa