分享
 
 
 

深入探索C++对象模型 之 构造,解构,拷贝语意学

王朝c/c++·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

纯虚拟函数的存在

一个pure virtual function 能被定义和静态地调用,不能经由虚拟机制调用。但是要不要定义又class 设计者决定。唯一例外的情况是pure virtual destructor ,class 设计者一定得定义它,因为一个derived class destructor 会被编译器加以扩展,以静态调用的方式调用其“每一个virtual base class”以及“上一层base class”的destructor。因此,只要缺乏任何一个base class destructors 的定义,就会导致链接失败。C++语言保证:继承体系中每一个class object 的destructors 都会被调用。所以编译器不能够压抑这个调用操作。一个比较好的替代方案就是,不要把virtual destructor 声明为pure 。

虚拟规格的存在

当一个函数定义的内容与类型无关时,不应该把他定义成virtual。一般而言,把所有的成员函数都声明为virtual function,然后再靠编译器的优化操作把非必要的virtual invocation 去除,并不是好的设计观念。

虚拟规格中const 的存在

虚拟函数最好不要声明成const ,因为你不能保证derived instance 不修改某个data member。

“无继承”情况下的对象构造

C中的struct:

在C中,全局变量如果没有明确的初始化操作,被认为是“临时性的定义”,在程序中可以发生多次,最后被链接器折叠起来,只留下单独一个实体,被放在程序 data segment 中一个“特别保留给未初始化的global objects 使用”的空间。又叫做“BSS”(Block Started by Symbol)。而C和C++ 的一个差异就在于,BSS data segment 在C++ 中相对地不重要。C++ 的所有全局对象都被当作“初始化过的数据”来支持。当然,如果一个local object 没有先经过初始化就使用它的初值的话,可能会成为一个潜在的程序臭虫。因为没有声明constructor ,那么用new 定义的object 也不会被初始化。

抽象数据类型(我们定义了一个constructor):

这次global object 将在程序激活时才开始初始化。而local object 和用new 运算符定义的object 变量也将被初始化。

为继承做准备(我们定义了一个constructor和一个virtual function):

这次class object 多了很多负担:vptr,constructor中附加的一些用来初始化vptr的码,合成一个copy constructor 和一个copy assignment operator,而且其操作是nontrivial(有用的)。

当有以传值方式返回对象的函数存在时,提供一个copy constructor 会触发NRV(Named Return Value)优化。

继承体系下的对象构造

构造的顺序:

1. 所有的 virtual base class constructors 必须被调用,从左到右,从最深到最浅:

Ø 如果class 被列于member initialization list 中,那么如果有任何明确指定的参数,都应该传递过去。若没有列于list中,而class 有一个default constructor ,也应该调用之。

Ø 此外,class中的每一个virtual base class subobject 的偏移量(offset)必须在执行期可被存取。

Ø 如果class object 是最底层(most-derived)的class,其constructors 可能被调用;某些用以支持这个行为的机制必须被放进来。

2. 所有上一层的base class constructors 必须被调用,以base class 的声明顺序为顺序(与member initialization list 中的顺序没关联):

Ø 如果class 被列于member initialization list 中,那么任何明确指定的参数,都应该传递过去。

Ø 若base class 没有列于member initialization list中,而它有一个default constructor (或default memberwise copy constructor),那么就调用之。

Ø 如果base class 是多重继承下的第二或后继的base class,那么this 指针必须有所调整。

3. 如果class object 有virtual table pointer(s),它(们)必须被设定初值,指向适当的virtual table(s)。

4. 记录在member initialization list 中的data members 初始化操作会被放进constructor 的函数本身,并以members 的声明顺序为顺序。

5. 如果有一个member 并没有出现在member initialization list 之中,但它有一个default constructor,那么该default constructor 必须被调用。

请注意,虽然一个class的destructor 是virtual 的,但是如果它被包含在另一个class中,那么它的调用操作会被静态决议出来。

虚拟继承:

传统的“constructor 扩充现象”并没有用,这是因为virtual base class 的“共享性”之故:

编译器给derived class 的constructor增加有个bool 参数,当是false 时,就不调用virtual base class的constructor。导致只有当一个完整的class object 被定义出来时,它才会被调用;如果object 只是某个完整object 的subobject,它就不会被调用。

Vptr 初始化语意学:

C++ 语言规定:在一个class(base class) 的constructor(和destructor) 中,经由构造中的对象(derived class)来调用一个virtual function,其函数实体应该是在此class(base class) 中有作用的那个。也就是都静态决议,不用到虚拟机制。也就是说,虚拟机制本身必须知道是否这个调用源自一个constructor 之中。而根本的解决之道是,在执行一个constructor 时,必须限制一组virtual functions 候选名单。答案是通过vptr。而vptr 的适当初始化时间是在base class constructors 调用操作之后,但是在程序员供应的码或是“member initialization list 中所列的members初始化操作”之前。因此在class 的constructor 的member initialization list 中调用该class 的一个虚拟函数是安全的,但是在一个class 的member initialization list 中供应参数一个base class constructor 时调用虚拟函数就是不安全的。

对象复制语意学

事实上,copy assignment operator 在虚拟继承情况下行为不佳,需要小心地设计和说明。因为 copy assignment operator 缺乏一个member assignment list(也就是平行与member initialization list 的东西),因此编译器没有办法压抑上一层的base class 的copy operators被调用,导致在虚拟继承情况下,derived class 将对virtual base class 进行多重拷贝。C++语言说:我们并灭有规定那些代表virtual base class 的subobjects 是否该被“隐喻定义(implicitly defined)的copy assignment operator”指派(赋值,assign)内容一次以上。因此建议尽可能不要允许一个virtual base class的拷贝操作,甚至可能的话,不要在任何virtual base class 中声明数据。

解构语意学

如过class 没有定义destructor,那么只有在class 内带的member object(或是class自己的base class)拥有destructor 的情况下,编译器才会自动合成出一个来。

Destructor 被调用的顺序:

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

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

3. 如果object 内带一个vptr,则现在被重新设定,指向适当之base class 的virtual table。

4. 如果有任何直接的(上一层)nonvirtual base classes 拥有destructor,它们会以声明顺序的相反顺序被调用。

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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有