文档详情

第10章面向对象程序设计语言.ppt

发布:2016-11-26约2.55万字共82页下载文档
文本预览下载声明
动态约束的实现:受限模型 早期?OO?语言(包括?Smalltalk)都采用功能强大灵活的对象模型? ·??在提供了极大灵活性的同时,也带来效率上的巨大开销 ·??这也是早期?OO?语言及其概念难被实际软件工作者接受的最关键原因 提高算法效率的最基本途径是限制要解决的问题(对?更?特?殊?一?些?的?问?题?,?可能找到效率更高的算法),并设计优化的实现模型 对于?OO?语言,就是要找到一个受限的对象模型,它能比较高效地实现,同时又能满足绝大部分实际?OO?程序开发的需要 常规?OO?语言中的对象模型有如下特性(足以支持常见程序设计工作)?:? ·??类层次结构是静态确定的? ·??每个类里的动态约束方法的个数和顺序都静态确定 在这种模型里就可以避免动态方法查找,使方法调用的执行效率接近普通的子程序调用的执行效率(C++?和?Stroustrup?的贡献) 动态约束的实现 优化实现模型,其中绝大部分工作都能静态完成: 每个类的运行时体现是一个动态约束方法的表(称为虚表,vtable),这是一个指针表,指针指向本类的对象需要调用的方法的代码体 虚表的指针按方法在类里的顺序排列,每个方法对应于一个顺序下标 动态约束的实现 在每个对象开头(数据域之前) 增加一个指针?vt 创建对象时,设置其?vt?指向 其所属的类的虚表(运行中始终不变) f?是指向?F?的指针(或引用) 调用?f-m(...)的实现 比调用静态约束的方法多了中间的两条指令,它们都需要访问内存 动态约束的实现 虚表的创建: 如果类?B?没有基类,就将其定义里的动态约束方法的代码体指针依次填入它的虚表(下标从?0?或者?1?开始算) 若类?D?的基类是?B,建立?D?的虚表时先复制?B?的虚表。如?D?覆盖了?B?的某个(某些)动态约束方法,就用新方法的指针覆盖虚表里对应的已有指针。若?D?定义了新的动态约束方法,就将它们顺次加入虚表,放在后面 如果?f?指向的对象是?B,那么?f-m(...)?也会调用正确的方法 动态约束的实现 重温受限的对象模型(对一般程序设计已经足够强大)?:? ·??类层次结构是静态确定的? ·??每个类里的动态约束方法的个数和顺序都静态确定 ? 优化实现的效果:? ·??构造方法表的工作在编译时完成? ·??每个对象里需要增加一个指向其类的方法表的指针? ·??每次方法调用需要多执行两条指令(典型情况),多访问内存两次 对这种受限对象模型,动态约束方法调用的额外开销不大,一般软件系统(包括系统软件的绝大部分情况)都可以接受 Stroustrup?在设计和实现?C++?语言时特别希望能够得到高效的实现,最后选择了这种对象模型,并设计了这种高效的实现方法 动态约束的实现 对数据抽象和面向对象技术的支持,以及高效的实现,使实际软件工作者看到了?C++(和?OO)的潜力,最终导致了面向对象的革命 以后的主流面向对象语言也都采用了这种技术。当然,采用这种选择,也就对它们可能采用的对象模型提出了严格的限制 Pragmatics?里本章最后的练习里还讨论了其他高效实现方法,《C++?语言的设计与演化》里也有讨论(通过几条指令构成的一段“蹦床代码”,将控制转到实际应该调用的方法,主要是要解决多重继承问题) 虚方法(动态约束方法)的一个重要缺点是不能做?inline?处理(在线展开要求静态确定被调用的方法),使编译器难以进行跨过程的代码优化 C++?希望支持高效的系统程序设计,认为虚方法带来的效率损失有时也是不能容忍的,因此它同时支持静态方法约束 注意:如果一个类里只有静态约束的方法,该类编译之后就不会生成方法表,该类的对象也没有一个指针的额外存储开销 类层次结构和强制转换 向上强制总是安全的,不会出问题,总可以自动进行。因为派生类包含基类所有数据成分,因此可以支持基类所有操作 后一个赋值是编译时错误,派生类指针不能引用基类对象 类层次结构和强制转换 如果用?foo?类的指针?q?传递一个对象 可保证该对象一定是?foo?的或它的某个派生类的对象? 如果由?foo?类指针?q?传递的实际上是一个?bar?对象,我们有时需要把它作为bar?对象使用,例如想对它调用?foo?里没有的方法 · q-s(..)?是静态类型错误(q?的指向类型是?foo,foo?无方法?s)? · s??=??q?也是静态类型错(不能保证?q?指向的是?bar,赋值不安全)? 能不能用?s??=??(bar*)q???? 如果?q?指向的确实是一个?bar?对象,当前情况下恰好可以,因为? ·??(bar*)?对指针是“非变换转换”,导致把?foo?指针当做?bar?指针? ·??恰好?
显示全部
相似文档