`

深度探索C++对象模型-- Data 语意学(阅读笔记)(原创)

c++ 
阅读更多

深度探索C++对象模型(阅读笔记)(原创)

Inside The C++ Object Model

 

                                                             --Data 语意学
由 王宇 原创并发布 


让我肃然起敬并崇拜的牛人

       Bjarne Stroustrup    -  C++之父    (www.stroustrup.com)

       Stanley B. Lippman  -  本书作者、C++代言人、C++编译器的设计者之一

       侯捷                         -  本书译者   (jjhou.boolan.com)

 

 第三章 Data 语意学

    3.1 Data Member的绑定

        例:

            extern float x;
            
            class Point3d
            {
                public:
                    point3d();
                    //问题:被传回和被设定的x是哪一个x呢?
                    float X() const
                    {
                        return x;
                    }
                    
                private:
                    float x, y, z;//Point3d::X()将返回内部的x。
            };

 

        在早期(2.0之前)C++的编译器上,将会指向global x object, 导致C++的两种防御性程序设计风格:    
            1、把所有的data members放在class 声明起头处,以确保正确的绑定
            2、把所有的inline functions, 不管大小都放在class声明之外

        对于 member function的argument list并不为真(同以上情况相反)。

        例:
 

           typedef int length;
            
            class Point3d
            {
                public:
                    //length 将被决议为global
                    //_val将被决议为Point3d::_val
                    void mumbel(length val)
                    {    
                        _val = val;
                    }
                    
                    length mumble()
                    {
                        return _val;
                    }

                private:
                    //导致 _val = val; return _val;不合法    
                    typedef float length;
                    length _val;    
            };

 

            预防性程序风格:请始终把“nested type 声明”放在class的起始处。

    3.2 Data Member的布局
        Nonstatic data member 在class object中的排列顺序将和其被声明的顺序一样,任何中间介入的static data members 如 freelist 和 chunkSize都不会被放入对象布局中

        传统上vptr放在所有明确声明member之后

    3.3 Data Member的存取
        Point3d origin, *pt = &origion;
        origin.x = 0.0;
        pt->x = 0.0;

        这两种方式的差异?

        Static Data Members:
            结论是完全相同, 原因是:每一个static data member 只有一个实体, 存放在程序的data segment之中, member其实并不在class object之中。
    
        Nonstatic Data Members:
            结论是完全相同,原因是:
                pt->x = 0.0; 方式:事实上是经由一个“implicit class object”(由this指针表达)完成


                    //member function 的内部转化
                    Point3d
                    Point3d::translate( Point3d *const this, const Point3d &pt)
                    {
                        this->x = pt.x;
                    }
                    
            
                origin.x = 0.0; 方式:class object的起始地址加上data member的偏移量(offset)
                    &origin + (&Point3d::_y - 1);

    3.4 "继承"与 Data Member    
        一个derived class object所表现出来的东西, 是其自己的member加上其base class(es) members的总和。图3.1b


 
        只要继承不要多态

            继承易犯的错误
                (1)重复设计一些相同的操作函数
                (2)把一个class分解为两层或更多层,有可能会为了“表现class体系之抽象化”而膨胀所需空间。(因为类型对齐,会浪费空间)    图p105    
                    
                填充空间的原因是为了复制对象时,避提高效率,免产生偏差。

            加上多态
                
                空间和存取时间的额外负担
                    (1)导入一个virtual table 和一个vptr
                    (2)加强constructor 和distructor 使其能够初始化和抹消virtual table和vptr    。

            把vptr放置在class object的那里会最好?
                (1)放在尾部保留C struct 的对象布局,C++最初期,这种方式被许多人采用。
                (2)放在前端,对于“在多重继承之下,通过指向class members的指针调用virtual function”,会带来一些帮助。当然代价就是丧失了C语言兼容性。

        多重继承
    
            多重继承的复杂度在于derrived class 和其上一个base class乃至于上上一个base class...之间的“非自然”关系。参考下列代码:
            

            class Point2d
            {
                public:
                protected:
                    float _x, _y;    
            
            };

            class Point3d : public Point2d
            {
                public:
                protected:
                    float _z;    
            
            };

            class Vertex
            {
                public:
                protected:
                    Vertex *next;    
            };

            class Vertex3d : public Point3d, public Vertex
            {
                public:
                protected:
                    float mumble;    
            
            };

 
                        
            下列操作并不需要编译器去调停或修改地址,它很自然地可以发生,而且提供了最佳执行效率。
                Point3d p3d;
                Point2d *p = &p3d;    
            
            多重继承的问题主要发生于derived class object 和其第二或后续的base class object之间的转换:

                Vertex3d  v3d;
                Vertex    *pv;
                Point2d   *p2d;
                Point3d   *p3d;

                  pv = &v3d;
                // 需要这样的内部转换:
                pv = (Vertex*)(((char*)&v3d) + sizeof(Point3d));

                // 下列转换只需要简单地拷贝地址就行了
                p2d = &v3d;    
                p3d = &v3d;


 
                参考图:3.4 p115

            C++ Standard 并未要求Vertex3d中的base classes Point3d和Vetex有特定的排列次序。原始的cfont编译器是根据声明次序来排序它们。目前各编译器仍然是以此方式完成多重base classes的布局(但如果加上虚拟继承,就不一样了)

        虚拟继承

            多重继承的一个语意上的副作用就是,它必须支持某种形式的“shared subobject继承”。参考图p117


 
            不论是istream或ostream都内含一个ios subobject。然而在iosstream的对象布局中,我们只需要单一一份ios subobject就好。语言层面的解决办法是导入所谓的虚拟继承

    3.5 对象成员的效率
        应该确实地测量效率,而不是靠着推论与常识判断。

    3.6 指向Data Members的指针
        class Point
        {
            public:
                virtual ~Point();
                static Point origion;
                float x,y,z;
        };

        如果vptr放在对象的尾端,则三个坐标值在对象布局中的offset分别是0,4,8。如果vptr放在对象的起头,则三个坐标值在对象布局中的offset分别是4,8,12.然而你若去取data members的地址, 传回的值总是多1, 就是1,5,9,或5,9,13

        如何区分一个“没有指向任何data member”的指针和一个指向“第一个data member”的指针?考虑下列例子:
        Point3d p3d;
        Point3d *p1 = 0;
        Point3d *P2 = &p3d;

        if( p1 == p2){};
        
        为了区分p1 和p2 ,每一个真正的member offset值都被加上1. 因此,无论编译器或使用者都必须记住,在真正使用该值以指出一个member之前,请先减掉1。
           

 

  • 大小: 36.8 KB
  • 大小: 78.2 KB
  • 大小: 28.7 KB
分享到:
评论

相关推荐

    深度探索C++对象模型---高清

    在深入探讨《深度探索C++对象模型》这一主题之前,我们首先需要理解C++对象模型的基本概念及其在程序设计中的重要性。C++作为一种广泛使用的编程语言,其强大的功能和灵活性使得它成为许多领域的首选语言之一。对于...

    深度探索C++对象模型-带目录书签.pdf

    《深度探索C++对象模型》是一本专注于C++编程语言底层机制的专业书籍,它深入剖析了C++的对象模型,帮助读者理解C++是如何在内存中表示对象、如何实现继承、多态等特性。这本书的内容涵盖了C++的核心概念,包括类、...

    深度探索C++对象模型 PDF中文清晰版

    《深度探索C++对象模型》专注于C++面向对象程序设计的底层机制,包括结构式语意、临时性对象的生成、封装、继承,以及虚拟——虚拟函数和虚拟继承。这本书让你知道:一旦你能够了解底层实现模型,你的程序代码将获得...

    深度探索c++对象模型(2012版本)

    《深度探索C++对象模型》是一本专注于C++底层机制的专著,主要针对2012年的标准进行深入解析。C++是一种多范式、静态类型、编译型、并发型、通用程序设计语言,它以其强大的功能和灵活性而闻名。这本书的目标是帮助...

    深度探索C++对象模型 超高清pdf

    深度探索C++对象模型 超高清

    深度探索C++对象模型.pdf

    ### 深度探索C++对象模型:理解与解析 #### C++对象模型概览 C++对象模型是C++编程语言中一个核心且复杂的概念,它定义了如何在内存中表示类、对象以及它们之间的关系。理解C++对象模型对于深入掌握C++语言特性、...

    深度探索C++对象模型(简体中文版).pdf

    在探索C++对象模型之前,首先需要理解对象模型(Object Model)的含义。对象模型是面向对象编程(Object-Oriented Programming,OOP)中的一个核心概念,它描述了对象的结构、属性、方法、以及对象之间的关系。C++...

    深度探索C++对象模型 中文pdf 英文chm

    深度探索C++对象模型 中文图片影印版pdf,比较清晰,不是那种模糊的版本,和文字版差别不大 英文清晰文字版chm 第一代C++编译器开发主管所写。如果你想成为真正的C++高手,看这本书,他为你讲述了编译器在处理各种...

    深度探索C++对象模型

    深度探索C++对象模型 第0章 导读(译者的话) 第1章 关于对象(Object Lessons) 加上封装后的布局成本(Layout Costs for Adding Encapsulation) 1.1 C++模式模式(The C++ Object Model) 简单对象模型(A Simple...

    深度探索C++对象模型 PDF中文清晰版.zip

    深度探索C++对象模型 PDF中文清晰版.zip深度探索C++对象模型 PDF中文清晰版.zip深度探索C++对象模型 PDF中文清晰版.zip深度探索C++对象模型 PDF中文清晰版.zip深度探索C++对象模型 PDF中文清晰版.zip深度探索C++对象...

    《深度探索C++对象模型》(Stanley B·Lippman[美] 著,侯捷 译)

    本书重点:探索“对象导向程序所支持的C++对象模型”下的程序行为。对于“对象导向性质之基础实现技术”以及“各种性质背后的隐含利益交换”提供一个清楚的认识。检验由程序变形所带来的效率冲击。提供丰富的程序...

    深入探索c++对象模型 设计模式c++ pdf

    《深入探索C++对象模型》是一本深度剖析C++编程语言内部机制的著作,而设计模式则是软件工程中的一种最佳实践,是解决常见问题的模板。这两者结合在一起,为开发者提供了理解C++如何实现面向对象特性以及如何高效地...

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

    通过阅读《深度探索C++对象模型》的学习笔记,我们可以更深入地理解C++的底层机制,这对于成为一名精通C++的开发者来说是必不可少的。同时,结合《Effective C++》的学习,可以让我们写出更加高效、健壮的C++代码。...

    深度解析C++对象模型--读书笔记

    总的来说,"深度解析C++对象模型"涵盖了C++语言中的核心概念,如类、对象、继承、多态、内存管理和模板,这些都是理解和编写高效C++代码的基石。通过深入学习和实践,开发者可以更好地掌握C++的精髓,编写出更加健壮...

    深度探索C++对象模型(中&&英文版)

    通过阅读《深度探索C++对象模型》,读者能够深入了解C++语言的底层机制,提升编程技能,更好地理解和调试复杂的C++代码。无论是对C++感兴趣的开发者,还是致力于成为C++专家的程序员,这本书都是不可或缺的参考文献...

Global site tag (gtag.js) - Google Analytics