1.全局对象

Matrix identity;main()
{// identity必须在此处被初始化Matric m1 = identity;...return 0;
}

像identity这样的所谓global object如果有constructor和destructor的话,我们说它需要静态的初始化操作和内存释放操作。

C++程序中所有的global objects都被放置在程序的data segment中。如果明确指定给它一个值,object将以该值为初值。否则object所配置到的内存内容为0。

int v1 = 1024;
int v2;

v1和v2都被配置于程序的data segment,v1值为1024,v2值为0(这个C略有不同,C并不自动设定初值)。在C语言中一个global object只能够被一个常量表达式(可在编译时期求值的那种)设定初值。当然,constructor并不是常量表达式。虽然class object在编译时期可以被放置于data segment中并且内容为0,但constructor一直要到程序激活(startup)时才会实施。必须对一个“放置于program data segment中的object的初始化表达式”做评估(evalute),这正是为什么一个object需要静态初始化的原因。

为每一个需要静态初始化的档案产生一个_sti()函数,内带必要的constructor调用操作或inline expansions;在每一个需要静态的内存释放操作的文件中,产生一个_std()函数,内带必要的destructor调用操作,或是其inline expansions。

2.Template的“具现”行为(Template Instantiation)

template <class Type>
class Point
{
public:enum Status { unallocated, normalized };Point(Type x = 0.0, Type y = 0.0, Type z = 0.0);~Point();void* operator new(size_t);void operator delete(void*, size_t);
private:static Point<Type>* freeList;static int chunkSize;Type _x, _y, _z;
};

首先,当编译器看到template class声明时,它会做出什么反应?在实际程序中,什么反应也没有!也就是说,上述的static data members并不可用。nested enum或其他enumerators也一样。

Point<float>::freeList;

Point class的float实体会被具现。

Point<double>::freeList;

Point class的double实体会被具现。

Point<float>* ptr = 0;

Point class不会被具现。因为一个指向class object的指针,本身并不是一个class object,编译器不需要知道与该class有关的任何members的数据或object布局数据。所以将“Point的一个float实体”具现也就没有必要。

const Point<float>& ref = 0;

一个Point的float实体会被具现出来。这个定义的真正语意会被扩展为:

Point<float> temporary( float(0) );
const Point<float>& ref = temporary;

为什么呢?因为reference并不是无物(no object)的代名词。0被视为整数,必须被转换为Point<float>的一个对象。如果没有转换的可能,这个定义就是错误的,会在编译时被挑出来。

所以,一个class object的定义,不论是由编译器暗中地做(上面的temporary),或是由程序员像下面这样明确地做:

const Point<float> origin;

都会导致template class的“具现”,也就是说,float instantiation的真正对象布局会被产生出来。

然而,member functions(至少对于那些未被使用过的)不应该被“实体”化。只有在member functions被使用的时候,C++ Standard才要求它们被“具现”出来。

目前的编译器,面对一个template声明,在它被一组实际参数具现之前,只能施行以有限的错误检查。template中那些与语法无关的错误,程序员可能认为十分明显,编译器却让它通过了。只有在每一个具现操作发生时才做类型检验。

template之中,对于一个nonmember name的决议结果是根据这个name的使用是否与“用以具现出该template的参数类型”有关而决定的。如果其使用互不相关,那么就以“scope of the template declaration”来决定name。如果其使用互有关联,那么就以“scope of the template instatiation”来决定name。

3.下面的class声明:

class PrimitiveObject : public Geometry
{
public:virtual ~PrimitiveObject();virtual void draw();...
};

如果它被含入15个或45个程序源码中,编译器如何能够确保只有一个virtual table实体被产生出来呢?编译器会把virtual table放在定义了该class的第一个non-inline、nonpure virtual function的文件中。以上面例子而言,编译器会将virtual table产生在储存着virtual destructor的文件之中。

4.异常处理:

欲支持exception handling,编译器的主要工作就是找出catch子句,以处理被丢出来的exception。这多少需要追踪程序堆栈中的每一个函数的当前作用区域(包括追踪函数中的local class objects当时的情况)。同时,编译器必须提供某种查询exception objects的方法,以知道其实际类型(这直接导致某种形式的执行期类型识别,也就是RTTI)。

如果是在Point ocnstructor中发生exception,此时内存已配置完成,那么Point之中任何构造好的合成物或子对象(subobject,也就是一个member class object或base class object)都将自动被解构掉,然后heap内存也会被释放掉。

类型描述器是必要的,因为真正的exception是在执行期被处理,其object必须有自己的类型信息。RTTI正是因为支持Exception Handling而获得的副产品。

当一个exception被丢出时,exception object会被产生出来并通常放置在相同形式的exception数据堆栈中。从throw端传染给catch子句的是exception object的地址、类型描述器(或是一个函数指针,该函数会传回与该exception type有关的类型描述器),以及可能会有的exception object描述器(如果定义的话)。

catch( exPoint p )
{// do somethingthrow;
}

考虑一个exception object,类型为exVertex,派生自exPoint。这两种类型都吻合,于是catch子句会作用起来。那么p会发生什么事?

1>p将以exception object作为初值,就像是一个函数参数一样。这意味着如果定义有(或由编译器合成出)一个copy constructor和一个destructor的话,它们都会实施于local copy身上。

2>由于p是一个object而不是一个reference,当其内容被拷贝的时候,这个exception object的non-exPoint部分会被切掉(sliced off)。此外,如果为了exception的继承而提供有virtual functions,那么p的vptr会被设为exPoint的virtual table;exception object的vptr不会被拷贝。

5.RTTI和dynamic_cast

程序执行中对一个class指针类型施以dynamic_cast运算符,会获得true或false:

如果传回真正的地址,表示这个object的动态类型被确认了,一些与类型有关的操作现在可以施行于其上;如果传回0,表示没有指向任何object,意味应该以另一种逻辑施行于这个动态类型未确定的object身上。

dynamic_cast运算符也适用于reference身上,但其结果不会与施行于指针的情况相同:

一个reference不可以像指针那样“把自己设为0便代表no object”,若将一个reference设为0,会引起一个临时性对象被产生出来,该临时对象的初值为0,这个reference然后被设定成为该临时对象的一个别名(alias)。

因此当dynamic_cast运算符施行于一个reference时,不能够提供对等于指针情况下的那一组true/false。取而代之的是,会发生下列事情:

1>如果reference真正参考到适当的derived class(包括下一层或下下一层...),downcast会被执行而程序可以继续进行;

2>如果reference并不真正是某一张derived class,那么,由于不能够传回0,于是丢出一个bad_cast exception。

[读书笔记] - 《深度探索C++对象模型》第6章 第7章相关推荐

  1. 第2章构造函数语义学读书笔记——深度探索c++对象模型

    深度探索c++对象模型 第2章 构造函数语义学 2.1 Default Constructor的构建操作 2.2 Copy Constructor的构造操作 2.3 程序转化语义学 2.4 成员的初始 ...

  2. 《深度探索C++对象模型》读书笔记第五章:构造析构拷贝语意学

    <深度探索C++对象模型>读书笔记第五章:构造析构拷贝语意学 对于abstract base class(抽象基类),class中的data member应该被初始化,并且只在constr ...

  3. [读书笔记]《深度探索C++对象模型》

    文章目录 前言 思维导图 第一章 关于对象 第二章 构造函数语意学 构造函数 拷贝构造函数 初始化列表 第三章 Data 语意学 第四章 Function 语意学 非静态成员函数 静态成员函数 虚成员 ...

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

    来源:http://dsqiu.iteye.com/blog/1669614 之前一直对C++内部的原理的完全空白,然后找到<Inside The C++ Object Model>这本书 ...

  5. 《深度探索C++对象模型》:简单对象模型、表格驱动模型、C++对象模型

    前言 对象模型是深层结构知识,关系到"与语言无关.与平台无关.跨网络可执行"软件组件的基础. C++相对于精瘦的C来说,多了许多特性,正因如此,我们更有必要去探索.了解C++对象模 ...

  6. 《深度探索C++对象模型》--5 构造析构拷贝 6 执行期语意学

     <深度探索C++对象模型>--5构造.析构.拷贝语意学 1.纯虚函数: (1)C++可以定义和调用一个纯虚函数,不过只可以静态调用,不可以由虚拟机制调用. 注意:pure virtu ...

  7. 深度探索C++ 对象模型(7)-Data member的布局(虚继承)

    虚拟继承 namespace ObjectMultiDerived {class Point2d {public:// has virtual functionsvirtual void print( ...

  8. 深度探索C++ 对象模型(7)-Data member的布局(多重继承)

    多重继承 namespace ObjectMultiDerived {class Point2d {public:// has virtual functionsvirtual void print( ...

  9. 深度探索C++ 对象模型(7)-Data member的布局(无继承、继承无多态、继承多态、多层继承)

    无继承 继承无多态 继承多态 虚表 : 用来存放基类的每一个虚函数,再加上首位的一个slots(支持RTTI). 每个class object导入一个vptr,提供执行期的链接,使得每一个class ...

  10. 深度探索C++ 对象模型(6)-Data member的存取

    nonstatic data member 需要在class object起始地址加上该member的偏移. class A {public: int x; int y;}; A a; a.y = 0 ...

最新文章

  1. 盘点 | 2018全球人工智能突破性技术TOP10(附报告)
  2. oracle变量最大多少位,oracle – 是否有可能获得变量的最大可能长度
  3. 5.1.2 操作系统控制I/O设备的I/O控制器
  4. 信息类产品检测培训讲义-EN55024
  5. 五年了,别再把务虚会开 “虚” 了
  6. 网页性能优化{雅虎[转载]}
  7. MySQL 浅谈NOT NULL和DEFAULT的关系
  8. sqlserver字符串拼接
  9. linux 使用秘钥认证,linux 密钥验证登录
  10. PPT分享 | 怎么在区块链上保护隐私?
  11. VASP服务器第一次安装各种软件(中)
  12. RingBuffer的快速上手使用方法
  13. 搜索命令:whereis/which/locate/find/grep
  14. OPENGL简介---反走样
  15. Decode函数的基本理解与简单应用
  16. 精灵复兴 与服务器链接中断,精灵复兴一键服务端+视频架设教程+GM模式介绍+2036合成公式+客户端...
  17. PARAMETERS、SELECTION OPTIONS和SELECTION SCREEN的全部用法
  18. java ssm集装箱码头TOS系统调度模块的设计与实现
  19. 思维导图怎么画,教你套用思维导图模板
  20. python进行 t 检验

热门文章

  1. pandas apply()函数传参,与解决TypeError: xxxx() takes 2 positional arguments but 3 were given报错
  2. Python把list变为str
  3. sparksql 操作hive_Spark SQL 物化视图原理与实践
  4. Codevs 1043 方格取数
  5. Java基础_学习笔记_13_类的多态性(二)
  6. 关于Toad的Cannot load OCI DLL问题
  7. HTML动画(难点)
  8. 采集练习(七) php 获得电视节目预告(一周节目)
  9. 网站安全检测 Web 安全测试工具
  10. AutoCAD 2010建筑土木制图高清实例视频教程