继承指针《深度探索C++对象模型》侯捷译——笔记(一),读后感,附带【插图】...

新手发帖,很多方面都是刚入门,有错误的地方请大家见谅,欢迎批评指正

    

一)、读后感

    在我参加任务两年多的时候,任务不算很忙了,《深刻理解C++对象模型》开始进入我的视野;或许是因为我要从Symbian.C++ 转向iOS Objective-C,并开始思考语言本身的一些东西的缘故。

    其实在一年前,出于对C++的迷惑,我已买了这本书。事先翻了几页竟然没懂,就搁那儿了!可是当初,它让我随身携带、恋恋不舍、是个旅途好伴侣;看到它我精神抖擞,它给了我继承做程序员的信心

    这段时光经常会在晚上11点后,关闭电脑,然后捧着书本儿吸取知识。这类感觉觉很不错!如果你在北京下班,那么不要在地铁上捧着手机看新闻、看微博和QQ,可以看点儿书。

    以上是我感叹,或许你认为我说的太罗嗦、夸大。我只能再引用李宗盛《鬼迷心窍》中的歌词:

        “有人问我你究竟是哪里好, 这么多年我还忘不了。“

         “春风再美也比不上你的好,没见过你的人不会明白。”

    我看的是左边“蓝绿色”的老版的,右边是2012版的。我看过新版的目录,跟老的基本一样。买新的吧

    继承和指针                           继承和指针

    浏览者要求。须要具有C++的基础知识。这本说就像译者评论的那样,不是婴幼儿奶粉,它是成人专用的低脂高钙特殊奶粉。假如把C++比喻成一辆汽车,这本书不是教你怎么开车,而是将汽车大卸八块,逐一部件剖析。

    这本说的作者也有一些地方是互相抵触的,很难理解,难道是C++太庞杂了么。

    专业术语介绍:

    

derived class派生类
base class基类
member function成员函数

    

nonvirtual function非虚函数

    

二)、回答几个小问题

    这本书的作者就是C++第一个编译器(cfront)的负责人,所以作者主要从编译器的角度来剖析C++的对象模型。

    第一个、一般来说在学习C++的时候,如果没有指明一个构造函数,那么系统会默认创建构造函数。非也,编译器会决议是否有必要生成一个构造函数和析构函数。也就默认构造函数可能不存在哦!特别是没有继承的情况下,编译器认为构造函数和析构函数是无用的。(参考p231)

    第二个、假设两个基类BaseABaseB都有virutal函数,BaseC继承自BaseABaseB,那么BaseC会有几个虚函数表?答案是:根据编译器不同而不同,有些是两个虚函数表。有些是一个表,比如sun的编译器。注意:这类情况属于多重继承,BaseC确定会有两个虚函数表指针

    第三个、局部变量和全局变量重名了,在局部变量的生命周期的大括号以内使用这个变量,那个起作用。当然是局部变量,但是C++并非从一开始就是这么计划的。

    一定要重复浏览第三章:Data语意学第四章:function语意学,和五章:构造、析构、拷贝语意学,这时平时开辟中最常见的。

    侯捷翻译的很不错,很多地方比如“虚函数”,基类,派生类,直接用virtual function 、base class derived class取代,很符合程序员的习惯。

    

上面开始条记本分

    

三)、类属性(Data语意学p83-p143)

    ---》一个空的类,巨细不是0而是1,因为编译器会生成一个隐晦的1bytes,用于区分,当该类多个对象时,各个对象都能在内存分配唯一地址。(p84)

    ---》成员变量的内存对齐,例如一个类只有char a一个属性; 但是它的巨细是4.虽然char的巨细是1。(p85)

    ---》为了坚持跟C的兼容性,C++不要求基类属性跟派生类属性的排列顺序,这个完整有编译器决议。(p88)

    ---》局部变量和全局变量重名情况,在局部变量的生命周期的大括号以内,使用该变量,哪个起作用?在1990年 随着The Annotated C++ Reference Manual修订,局部变量开始隐藏全局同名变量。而之前则是不隐藏。(p89)

    ---》属性的内存顺序和声明顺序是分歧的。不同级别(public、protected和private)属性的排列顺序是绝对分歧的,就是说可能不连续,但是必须符合较晚出现的属性存在较高的地址。(p92)

    ---》虚函数表指针Vptr,可能存在类的开始,也有可能存在类的末尾。通常都是类的末尾。(p92,p111,p112)

    首先介绍vptr存在末端模式。下图演示单一继承并含有虚函数情况下的数据布局(自然多态)。Point2d 和Point3d是继承关系,注意:Vptr放在类的末尾。

    继承和指针

    继承和指针

    初学者不要以为派生类的虚函数表指针Vptr(类结构中存的是虚函数表指针,并非虚函数表)存在派生类的那个部位,它依然是在父类的完整对象结构中

    只不过,在派生类构造的时候,会将vptr所指向的virtual table修改。

    vptr在前端模式,这么做丧失了与C的兼容性。

    继承和指针

    如果是前端寄存,还存在一个问题:如果基类没有虚函数,派生类有虚函数,那么单一继承的自然多态就会被攻破。如果要将派生类转换成基类,必须编译器的参与。(p112)

    继承和指针

    编译器仿佛开始施展它的作用了。多重继承下又是虚拟继承,编译器必须做出必要的偏移和调整,才能保障正确的调用虚函数。

    ---》对一个类对象取地址,那么并非第一个属性的地址,第一个属性的地址还须要+1,这么做是为了区分指向第一个属性和指向所有属性的指针两种情况。(p98)

    ---》一般而言,基类属性在派生类的开始部份,但是C++任何一条规则,只要碰上虚继承就没辙儿了。(p99)

    ---》C++语言保障“出当初派生类中的基类对象,有其完整性”,这么做是为了在位拷贝的时候,能够拷贝正确。(p106)

    假如ClassA 和ClassB都有一个char的属性,假设ClassB 继承自ClassA,假设,C++为了节俭内存,将自己的char类型和基类的char类型绑定一同,那么经过上面表达式后可能出现问题:

    ClassA* a = new ClassB;

    ClassB b = *a;

    下图描述的是“紧凑类型”,这样会致使严重后果,派生类的属性可能被“抹掉”,如图中的char b

    继承和指针继承和指针

    不要以为ClassB中的char b和ClassA中的char 会放在一同,由于内存对齐的规则,ClassA巨细是4B,ClassB巨细是8B。这样即使拷贝就不会出问题。

    下图描述的是父类在子类中有完整的对象结构:

    继承和指针

    (一样就像刚才我说的那样:虚拟继承将破坏这类父类结构的完整型)

    ---》单一继承下,父类通常在派生类前端。所以不管继承有多深,把一个derived class指定给class,该操作不须要编译器的参与。多重继承既不像单一继承,也不轻易模拟出其模型,多重继承的庞杂度在于derived class和其上一个base class 乃至于上上一个base class......之间的“非自然”关系,(p112)

    多重继承的问题主要发生于derived class和其第二或后继的base class 之间的转换。

    对于一个多重派生对象,将其地址指定给“最左端(也就是第一个)基类的指针”,情况和单一继承时雷同,因为两者都指向雷同的肇端地址。须要付出的本钱只是地址的指定操作而已,至于第二个或后继的base class的地址指定操作,则须要进行地址修改:加上或者减去介于中间base class巨细。

    下图展示了多继承的关系。涉及到4个类 Point2d、Point3d、Vertex和Vertex3d(p115)

    继承和指针

    继承和指针

    上面展示了多重继承的对象模型。

    继承和指针

    继承和指针

    多继承的情况下,drived clas可能会有两个或两个以上虚函数表指针

    请看上面的表达式:

    Vertex3d v3d;

    Vertex *pv;

    Point2d *p2d;

    Point3d *p3d;

    那么这个操作 pv = &v3d  须要转换内部代码pv = (Vertex*)(((char*)&v3d) + sizeof(Point3d));

    上面这两个操作,只须要拷贝地址就好了。

    p2d = &v3d;

    p3d = &v3d;

    ---》虚拟多继承情况(p117)

    下图可以表现Vertex3d 的继承体制图。左为多重继承,右为虚拟多重继承。

    继承和指针

    不论是Vertex还是Point3d都内含一个Point2d。然而在Vertex3d的对象布局中,我们只须要单一一份Point2d就好。所以引入虚拟继承。然而编译器要实现虚拟继承,实在是困难度颇高。虚拟继承的原则就是:让VertexPoint3d各自维护的Point2d 折叠成一个有Vertex3d维护的单一Point2d,并且还可以保存base class 和derived class的指针之间的多台指定操作。

    如果一个class含有virtual base class 那么,该对象将被分割为两部份:一个稳定局部和一个同享局部。稳定局部中的数据,不管后继如何演变,总是拥有牢固的offset,所以这部份数据可以直接存取。至于同享局部(即virtual base class),这一部份的数据,其位置会因为每次的派生操作而有变更,所以他们只能被直接存取。各家编译器实现技术之间的差异就是直接存取的方法不同,当初有三种主流策略。

    第一个策略:如何存取class的同享局部呢?cfront编译器会在每一个derived class中安插一个指向virtual base class的指针,这样就可以直接存取。这样的实现模型会有上面两个主要缺陷:

    1.每一个对象必须针对其每一个virtual base class 背负一个额定的指针。

    解决方法有:第一个,Microsoft编译器引入所谓的virtual base class table。每一个class object如果有一个或多个virtual base class,就会由编译器安插一个指针,指向virtual base class table。至于真正的virtual base class 指针,当然是被放在该表格中。

    请看上面的虚拟继承对象模型,如图。

    继承和指针

    红框内即所谓的“同享局部”,其位置会因每次派生操作而有所变更。虚拟破坏了base class 的对象完整型,虚拟继承会在自己类中生成一个虚函数表指针。

    第二个、在virtual function table 中放置virtual base class的offset(不是地址)。

    继承和指针

    这个方法的好处是,奇妙的利用了虚函数表的结构,使得drived class 能够节俭一个指针的巨细。上图中国蓝色曲线是offset

    2.由于虚拟继承串链的加长,致使直接存取层次的增长。例如:如果我们有三层虚拟衍化,我就须要三次直接存取(经过三个virtual base class指针)。

    这个问题的解决方案有:拷贝所有的virtual base class 的指针到drived class中。这样就解决了存取时光的问题,虽然会有空间的开销。

    一般而言,virtual base class 最有效的一种运行形式就是:一个抽象的virtual base class 没有任何的data members。或许正是java和Objective-c不使用多重继承,却使用接口类(OC叫协议)的原因。

    ---》如果对类的属性取地址(p130)

    比如 &Point3d::z失掉的值将是z在所有属性中偏移量。

    打印该值的时候必须使用这个方法   :printf("&Point3d::z =%p\n",&Point3d::z);

    

四)、类方法(function语意学p139-p186)

    每日一道理
信念是巍巍大厦的栋梁,没有它,就只是一堆散乱的砖瓦;信念是滔滔大江的河床,没有它,就只有一片泛滥的波浪;信念是熊熊烈火的引星,没有它,就只有一把冰冷的柴把;信念是远洋巨轮的主机,没有它,就只剩下瘫痪的巨架。

    ---》 C++的成员函数有三种:static 、nonstatic和virtual。每一种类型的调用方法都不同。(p140)

    ---》C++的计划原则之一就是nonstatic member function至少必须和一般的nonmember function有雷同的效率。而实际上成员函数也是被转化为nonmember function调用,上面是转化步骤:(p142)

    1.改写函数的签名(signature,函数名称+参数数目+参数类型)安插一个this指针到函数参数中来。

    例如:float Point3d::magnitude3d()const;

    经过改写后的方法为:float Point3d::magnitude3d(const Point3d* const this)const

    ***这也就是问什么:const  可以用来区分重载函数的标示的,包括const参数或const函数,但是返回值不算,因为返回值不会作为函数的签名。

    2.对nonstatic data member 的存取操作改为经过this指针来完成。

    3.将member function从新写成一个外部函数。对函数进行mangling(从新命名)处置,是它在程序中成为独一无二的语汇。

    ---》一般而言,member function(data member也是一样)的名称前面会被加上class名称,形成独一无二的命名。(p144)

    ---》当初C++编译器对name mangling的做法还没有同一,但是迟早会同一。(p145)

    ---》虚函数(p147)

    如果函数normalize()是一个虚函数,那么上面的调用 ptr->normalize()将被内部转化为:

    (*ptr->vptr[1])(this); vptr是有编译器发生的指针,指向virtual table。下标为1说明是是第1个虚函数。

    ---》静态成员函数将被转化为一般的nonmember函数调用。它不能存取nonstatic members,不能声明为:const、volatile或virtual。

    由于静态成员函数缺乏this指针,因此其差不多等同于nonmember function。它提供了一个意想不到的好处:成为callback函数。

    ---》虚拟成员函数(p152)

    在C++中多态(polymorphism)表现”以一个public base class的指针(或者reference),寻址处一个derived class object“的意思。

    在C++中virtual functions可以在编译时期获知,这一组地址是牢固稳定的,执行期不可能新增或者替换值。

    请看上面一个类Point的定义:

    class Point {

    public:

          virtual ~Point();

          virtual Point& mult(float)=0;

          float x()const {return _x;}

          float y()const {return 0.0;}

          float z()const {return 0.0;}

    protected:

        Point(float x=0.0);

        float _x;

    };

    Point2d继承自Point。Point3d继承自Point2d。那么内存模型如图,单一继承情况

    继承和指针

    在单一继承体制中,virtual function机制的行为非常精良,不但有效率而且很轻易塑造其模型出来,但是在多重继承和虚拟继承中,对virtual function的支撑就没有那么美好了

    ---》thunk技术(p162)

    所谓的thunk是一段assembly码,用来以适当的offser值调整this指针,跳到virtual function去。Thunk技术允许virtual table slot 继承内含一个简单的指针,因此多重继承不须要任何空间上的额定负担。slots中的地址可以直接指向virtual function,也可以指向一个相干的thunk。

    ---》vptr将在构造函数中被设立初始值。(p164)

    ---》多重继承下的虚函数

    多重继承下,通常派生类会有多个virtual table ,最左边基类的称之为:“主要表格”,第二或更过多基类的表格称为:“次要表格”(参考上图),派生类的主要表格和次要表格可以连在一同,比如Sun的编译器的策略就是这样的。(p164,p165)

    class drived 继承自 class Base1 class Base2 类结构如下:

    class Base1{                                      class Base2{

    public:                                                    public:

          Base1();                                                      Base2();

          virtual ~Base1();                                        virtual ~Base2();

          virtual void SpeakClearly();                     virtual void mumble();

          virtual Base1* clone() const;                   virtual Base2* clone()const;

    };                                                                };

    这两个类我故意并列在一同,Base1和Base2的区别就是两个不同的虚函数void SpeakClearly()和void mumble();

    class Derived: public Base1,public Base2{

    public:

            Derived();

            virtual ~Derived();

            virtual Derived* clone()const;

    protected:

            float data_derived;

    };

    那么这几个类的virtual table的布局如下:

    继承和指针

    继承和指针

    继承和指针

    多重继承下:derived类会分别重写“主要表格”和“次要表格”

    ---》虚拟继承下的虚函数。

    继承和指针

    

    

    ---》当然这本说也不是如此的深刻,当一个virtual base class 从另外一个virtual base class派生而来,并且两者都支撑virtual functions和nonstatic data members时,编译器对于virtual的支撑简直就像进入迷宫一样。作者只是给了一句话“距离庞杂的深渊悬崖不远了。”(p169)

    ---》获取一个nonstatic member function的地址,如果该函数是non virtual,则失掉的结果是它在内存中的真实地址。然而这个地址是不全的,他也须要被绑定与某个class object的地址上(this指针),才能过通过它调用函数。(p174)

    ---》获取一个virtual member function的地址,只能获取一个索引值。(p176)

    那么,如果使用一个函数指针float (Point::*pmf)() = &Point::z;这时pmf是一个索引值。

    但是,pmf还可以指向一个nonvirtual member function的真实地址啊?cfront的做法是如果pmf大于127就是真实地址,如果小于127就是索引值。当然这类计划限定了继承体制中只能有128个virtual function,这并非我们希望看到的。在多重继承的引入后又有了别的方法解决这个问题。然而,刚刚说的这个方法就淘汰了。(p178)

    ---》多重继承下,指向member functions的指针。指向member function的指针须要先指向一个结构体,该结构体中寄存几个属性分别表现virtual table的索引和non virtual member function的地址。详情见(p179)

    ---》inline函数提供了一个强有力的工具。然后与non-inline函数比起来,他们须要更小心的处置。

    

五),构造、析构和拷贝语意学(p191-p236)

    看第五章跟打游戏一样,看着看着不行了,看不懂了,这关没过去,还得从头儿再来。

    ---》每一个derived class destructor 会被编译器加以扩展,以静态调用的方式调用其“每一个virtual base class”已“上一层base class”的destructor。所以virtual function不要声明为pure(p193)

    point的声明

    type struct

    {

        float x,y,z;

    }Point;

    point的使用:

    Point global;

    Point foobar()

    {

        Point local;

        Point *heap = new Point;

        *heap = local;

        delete heap;

        return local;

    }

    观念上Point的构造函数和析构函数会被编译器创建,事实上并非如此:Point被编译器看做是Plain Ol' Data。

    ---》无继承情况下的对象构造(p196)

    ---》不论是private、public存取层,或是member function的声明,都不会占用对象的空间。(p199)

    ---》constructor可能内带大量隐藏代码,因为编译器会扩充每一个constructor,大致有上面几种情况:(p206)

        1.初始化“初始化列表中的数据”

        2.如果data member没有出当初初始化列表中,将调用data member的constructor。

        3.如果有vptr进行初始化。

        4.上一层的base class constructor必须呗调用,以base class的声明顺序为准。

        5.所有virtual base class constructor必须被调用。

    ---》虚拟继承下的构造函数。(p210)

    如下图的继承关系。

    继承和指针

    如果Vertex3d构造的时候,必然调用Point3d的构造函数,同时调用Vertex的构造函数,然而这两个类都要必须调用Point2d的构造函数,这是不合理的。取而代之的是应该在Vertex3d的构造函数中直接对Point2d初始化。这样就须要Vertex3d再条用Point3d或者Vertex的构造函数的时候传递一个bool参数__most_derived,即“是否是最后一层继承关系”,然后Point3d或者Vertex的构造函数根据这个bool变量决议是否构造Point2d。

    总结为一句话:virtual base class constructor,只有当一个完整的class object被定义出来时,它才会被调用。如果object只是某个完整的object的suboject

    ,他就不会被调用。

    ---》vptr的初始化(p213)

    在base class constructor调用操作之后,但是在程序员提供的代码或是“member initialization list中所列的members初始化操作”之前编译器对vptr进行初始化。这个过程就像想象的那样:一个PVertex对象会先成为一个point2d对象。一个point3d对象、一个vertex对象和一个vertex3d对象,最后才成为一个PVertex对象。

    ---》一个构造函数的真实步骤可能如下:(216)

        1.在derived class constructor 中,“所有virtual base classes”及“上一层base class”的constructor会被调用。

        2.上述完成后,对象vptr(可能多个vptrs)被初始化,指向相干的virtual table(可能多个表)

        3如果有member initialization list 的话,将在constructor体内扩展开来。这必须在vptr被设定之后才进行,以免有一个virtual member function被调用。

        4.最后,执行程序员所提供的代码。

    ---》如果不准将一个class object指定给另外一个class object,那么只要将copy assignment operator声明为private即可。(p219)

    ---》析构函数(p231)

    如果class 没有定义destructor,那么只有在class内带的member object(或是class自己的base class)拥有destructor的情况下,编译器才会自动合成出一个来。否者destructor被视为不须要,也就不须要合成(当然更不须要调用)

    ---》析构函数的实际操作可能如下:

        1.destructor的函数本身首先被执行

        2.如果class拥有member class objects,而后者拥有destructor,那么它们会以其声明顺寻的反序被调用。

        3.如果object内带一个vptr,则当初被从新设定,指向适当的base class的virtual table

        4.如果有任何直接的nonvirtual base lasses 拥有destructor,它们会以其声明的反序被调用。

        5.如果有任何 virtual base class拥有destructor,而当前讨论的这个class是最末端(most-derived)的class,那么它们会以其原来的构造顺寻的相反顺寻被调用。

    

    以上是第三章、第四章和第五章的主要内容。

 - - - - - - - - -未完待续---------- 剩余章节会新写一个blog- - - - - - - - - - - 

    

六、C++大记事:

    1993年引入RTTI。

        1990 随着The Annotated C++ Reference Manual修订,局部变量开始隐藏全局同名变量。

        1989年,发布了Release 2.0。引入了多重继承、抽象类、常数成员函数,以及成员保护。

    1987年 引入静态成员函数。

    20世纪80年代中期引入虚函数。

    

    从某种角度上来说,C++的强大要归功与C++的编译器的强大。这时我才知道为什么用很厚一本书来介绍visual studio,可能也是Symbian不用标准C++的原因。

    

    如有问题,欢迎大家斧正!

    

文章结束给大家分享下程序员的一些笑话语录: 关于编程语言
如果 C++是一把锤子的话,那么编程就会变成大手指头。
如果你找了一百万只猴子来敲打一百万个键盘,那么会有一只猴子会敲出一 段 Java 程序,而其余的只会敲出 Perl 程序。
一阵急促的敲门声,“谁啊!”,过了 5 分钟,门外传来“Java”。
如果说 Java 很不错是因为它可以运行在所有的操作系统上,那么就可以说 肛交很不错,因为其可以使用于所有的性别上。

本书重点:探索对象导向程序所支持的C++对象模型”下的程序行为。对于“对象导向性质之基础实现技术”以及“各种性质背后的隐含利益交换”提供一个清楚的认识。检验由程序变形所带来的效率冲击。提供丰富的程序范例、图片,以及对象导向观念和底层对象模型之间的效率测量。 C++成山似海的书籍堆中,这一本不是婴幼儿奶粉,也不是较大婴儿奶粉,它是成人专用的低脂高钙特殊奶粉。 对于C++底层机制感兴趣的读者,这本书会给你“漫卷诗书喜欲狂”的感觉。 了解C++ Object Model,是学习Component ObjectModel的最短路线。 如果你是一位C++程序员,渴望对于底层知识获得一个完整的了解,那么Inside TheC++ Object Model正适合你。 目录: 本立道生(侯捷 序) 前言(Stanley B.Lippman) 第0章 导读(者的话) 第1章 关于对象(Object Lessons) 加上封装后的布局成本(Layout Costs for Adding Encapsulation) 1.1 C++模式模式(The C++ Object Model) 简单对象模型(A Simple Object Model) 表格驱动对象模型(A Table-driven Object Model) C++对象模型(The C++ Object Model) 对象模型如何影响程序(How the Object Model Effects Programs) 1.2 关键词所带来的差异(A Keyword Distinction) 关键词的困扰 策略性正确的struct(The Politically Correct Struct) 1.3 对象的差异(An Object Distinction) 指针的类型(The Type of a Pointer) 加上多态之后(Adding Polymorphism) 第2章 构造函数语意学(The Semantics of constructors) 2.1 Default Constructor的建构操作 “带有Default Constructor”的Member Class Object “带有Default Constructor”的Base Class “带有一个Virual Function”的Class “带有一个virual Base class”的Class 总结 2.2 Copy Constructor的建构操作 Default Memberwise Initialization Bitwise Copy Semantics(位逐次拷贝) 不要Bitwise Copy Semantics! 重新设定的指针Virtual Table 处理Virtual Base Class Subobject 2.3 程序转换语意学(Program Transformation Semantics) 明确的初始化操作(Explicit Initialization) 参数的初始化(Argument Initialization) 返回值的初始化(Return Value Initialization) 在使用者层面做优化(Optimization at the user Level) 在编器层面做优化(Optimization at the Compiler Level) Copy Constructor:要还是不要? 摘要 2.4 成员们的初始化队伍(Member Initialization List) 第3章 Data语意学(The Semantics of Data) 3.1 Data Member的绑定(The Binding of a Data Member) 3.2 Data Member的布局(Data Member Layout) 3.3 Data Member的存取 Static Data Members Nonstatic Data Member 3.4 “继承”与Data Member 只要继承不要多态(Inheritance without Polymorphism) 加上多态(Adding Polymorphism) 多重继承(Multiple Inheritance) 虚拟继承(Virtual Inheritance) 3.5 对象成员的效率(Object Member Efficiency) 3.6 指向Data Members的指针(Pointer to Data Members) “指向Members的指针”的效率问题 第4章 Function语意学(The Semantics of Function) 4.1 Member的各种调用方式 Nonstatic Member Functions(非静态成员函数) Virtual Member Functions(虚拟成员函数) Static Member Functions(静态成员函数) 4.2 Virtual Member Functions(虚拟成员函数) 多重继承下的Virtual Functions 虚拟继承下的Virtual Functions 4.3 函数的效能 4.4 指向Member Functions的指针(Pointer-to-Member Functions) 支持“指向Virtual Member Functions”之指针 在多重继承之下,指向Member Functions的指针 “指向Member Functions之指针”的效率 4.5 Inline Functions 形式对数(Formal Arguments) 局部变量(Local Variables) 第5章 构造、解构、拷贝 语意学(Semantics of Construction,Destruction,andCopy) 纯虚拟函数的存在(Presence of a Pure Virtual Function) 虚拟规格的存在(Presence of a Virtual Specification) 虚拟规格中const的存在 重新考虑class的声明 5.1 无继承情况下的对象构造 抽象数据类型(Abstract Data Type) 为继承做准备 5.2 继承体系下的对象构造 虚拟继承(Virtual Inheritance) 初始化语意学(The Semantics of the vptr Initialization) 5.3 对象复制语意学(Object Copy Semantics) 5.4 对象的功能(Object Efficiency) 5.5 解构语意学(Semantics of Destruction) 第6章 执行期语意学(Runting Semantics) 6.1 对象的构造和解构(Object Construction and Destruction) 全局对象(Global Objects) 局部静态对象(Local Static Objects) 对象数组(Array of Objects) Default Constructors和数组 6.2 new和delete运算符 针对数组的new语意 Placement Operator new的语意 6.3 临时性对象(Temporary Objects) 临时性对象的迷思(神话、传说) 第7章 站在对象模型的类端(On the Cusp of the Object Model) 7.1 Template Template的“具现”行为(Template Instantiation) Template的错误报告(Error Reporting within a Template) Template中的名称决议方式(Name Resolution within a Template) Member Function的具现行为(Member Function Instantiation) 7.2 异常处理(Exception Handling) Exception Handling快速检阅 对Exception Handling的支持 7.3 执行期类型识别(Runtime Type Identification,RTTI) Type-Safe Downcast(保证安全的向下转型操作) Type-Safe Dynamic Cast(保证安全的动态转型) References并不是Pointers Typeid运算符 7.4 效率有了,弹性呢? 动态共享函数库(Dynamic Shared Libraries) 共享内存(Shared Memory)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值