设为首页 加入收藏

TOP

关于C++对象模型的深入理解(五)
2018-03-14 09:00:23 】 浏览:786
Tags:关于 对象 模型 深入 理解
一个section先出现的template function:

template

char* access_order(data_type1 class_type::*mem1,data_type2 class_type::*mem2)

{

assert(mem1 != mem2);

return mem1 < mem2 “member 1 occurs first” : “member 2 occurs first”;

}

(我在VC++ 6.0下测试该函数,编译尚未通过。这个,应该怪罪编译器)

2002-7-6

3.3 Data Member的存取

1.不管什么情况,每一个static data member只有一个实体,放在程序的data segment之中,每次程序取用static member,不管是通过operator::还是member selection operator,都会被内部转化为对该唯一extern实体的直接参考操作。每一个static member的存取以及与class的关联不会导致任何执行时间或空间上的额外负担。如果有两个classes,每一个都声明了一个static member freeList,那么当它们都放在程序的data segment时,就会导致名称冲突,编译器的解决方法是使用name-mangling,暗中对每一个static data member编码,以获得一个独一无二的程序识别代码。

2.有多少个编译器,就有多少种name-mangling做法,任何name-mangling做法都有两个要点:

ü一种算法,推导出独一无二的名称;

ü如果编译系统或者环境工具必须和使用者交谈,那些独一无二的名称可被轻易推导回原先的名称。

3.取一个static data member的地址,会得到一个指向其数据类型的常量指针,而不是指向其class member的指针。

4.nonstatic data members直接放在每一个class object之中,除非经过显示的explicit或隐含的implicit class object,没有办法直接存取它们。只要程序员在一个member function中直接处理一个nonstatic data member,所谓implicit class object就会发生,其实质是编译器会为这个member function增添一个const this指针,而在函数体内通过这个this指针来存取nontatic data member。

5.欲对一个nonstatic data member进行存取操作,编译器需要把class object的起始地址加上data member的编译量offset,如地址&someObject.someMember等于&someobject + (&theClass::someMember – 1);指向data member的指针,其offset值总是会被加上1,这样可以使编译系统区分出一个指向class第一个data member的指针和一个没有指向任何data member的指针。

6.每一个nonstatic data member的偏移量在编译时期即可获知,甚至如果member属于一个单一或多重继承体系中base class subobject也是一样,因此其存取效率和一个C struct member或一个nonderived class的member的存取效率是一样的。但是在虚拟继承的情况下就另当别论了:如果该nonstatic data member是一个virtual base class的member,并且通过指针来存取的话,在编译时期就不会得知这个member真正的offset位置,所以这个存取操作必须延迟至执行期,经由一个额外的间接导引才能够解决。

2002-7-7

3.4“继承”与Data Member

1.在C++继承模型中,一个derived class object所表现出来的东西,是其自己的members加上其base classes members的总和。C++并未规定derived class members和base classes members的排列次序。不过,在大部分编译器上,除virtual base class外,base class members总是先出现。

2.一般而言,具体继承concrete inheritance并不会增加空间或存取时间上的额外负担。

3.把两个原本独立不相干的classes凑成一对type/subtype,并带有继承关系容易犯两个错误。一是可能会重复设计一些相同操作的函数,一般而言,选择某些函数做成inline函数,是设计class的一个重要课题;二是把一个class分解为多层,有可能会为了表现class体系之抽象化,因为编译器的边界调整而膨胀所需空间。其根本原因是C++保证出现在derived class中的base class subobject有其完整原样性。

4.C++最初问世时,许多编译器把vptr放在class object的尾端,这样可以保留base class C struct的对象布局。此后,某些编译器开始把vptr放在class object的开始处,这样会给多重继承下通过指向class members之指针调用virtual function带来一些帮助,否则,在执行期不仅必须备妥从class object起点处开始量起的offset,而且必须备妥class vptr之间的offset。

5.单一继承提供了一种自然多态的形态,是关于class体系中base type和derived type之间的转换。一般来说,base class和derived class objects都是从相同的地址开始。但若将vptr放在class object的起始处,如果base class没有virtual function而derived class有,那么单一继承的自然多态就会打破。此时,把一个derived object转换为其base类型就需要编译器的介入,用以调整地址。而在既是多重继承又是虚拟继承的情况下,编译器的介入则更有必要。

6.多重继承的复杂度在于derived class和其上一个base class乃至上上一个base class之间的非自然关系,其主要问题发生在derived class objects和其第二或后继的base class objects之间的转换。对一个多重派生对象,将其地址指定给最左端base class的指针,情况将和单一继承相同,而第二个或后继的base class的地址指定操作则需要修改地址,加上或减去(若是downcast)介于中间的base class subobjects的大小。C++并未要求多重继承时derived class object中各个base class subjectes的排列次序,目前各个编译器都是根据声明次序来排列它们。

7.class内如果内含一个或多个virtual bass class subobjects,将被分割为两部分:一个不变局部和一个共享局部。不变局部总是拥有固定的offset,其数据用以指定共享局部的位置,可以直接存取;而共享局部表现的就是virtual base class subobject,其位置会因为

首页 上一页 2 3 4 5 6 7 下一页 尾页 5/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇万能的C++头文件分享 下一篇C++设计模式之原型模式(克隆羊多..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目