游戏开发论坛

 找回密码
 立即注册
搜索
楼主: bluebaby9811

如何保证一个对象最先构造,最后析构?

[复制链接]

30

主题

422

帖子

433

积分

中级会员

Rank: 3Rank: 3

积分
433
发表于 2009-11-19 21:24:00 | 显示全部楼层

Re: Re: Re: Re: Re:如何保证一个对象最先构造,最后析构?

bluebaby9811: Re: Re: Re: Re:如何保证一个对象最先构造,最后析构?
是啊,你已经说了无论何处第一次使用MyClass::GetInstance()必然给你一个有效的对象,也可以理解为直到第一次调用MyClass::GetInstance()它才给你一个有效的对象,所以用来解决我们的问题有点勉强了。

活活让你给曲解了.
只要所有要访问MyClass的用户都使用GetInstance方法访问,那么就不存在第一次调用之前对这个对象的访问了。

45

主题

157

帖子

169

积分

注册会员

Rank: 2

积分
169
QQ
 楼主| 发表于 2009-11-19 22:47:00 | 显示全部楼层

Re: Re: Re: Re: Re: Re:如何保证一个对象最先构造,最后析构?

kaikai: Re: Re: Re: Re: Re:如何保证一个对象最先构造,最后析构?


活活让你给曲解了.
只要所有要访问MyClass的用户都使用GetInstance方法访问,那么就不存在第一次调用之前对这个对象的访问了。

是不是曲解,我想仁者见仁,智者见智吧!我们只要对比一下就知孰优孰劣了。
  先来看Singleton解决方案吧,如果我要在客户类对象构造之初(注意这里是之初而不是当初的之前)就需要一个服务类的实例存在,所以我必须在客户类的每个构造函数里调用GetInstance()来实例它,并且这个调用还要放在构造函数的最开始处。
  再来看我们的解决方案,因为服务类对象是客户类的成员,C++的构造机制会保证服务类对象的构造在客户类构造函数体内所有语句之前(这才能说之前),并且这是编译器自动完成的,并对客户类所有构造函数都成立,参见effectiveC++条款12。
  我们有如此完美的语言机制,为和还靠人工来完成呢!

30

主题

422

帖子

433

积分

中级会员

Rank: 3Rank: 3

积分
433
发表于 2009-11-20 12:11:00 | 显示全部楼层

Re:如何保证一个对象最先构造,最后析构?

之所以希望在某时间之前让某对象存在,是因为存在一种依赖关系。
那么既然有依赖关系,就应当显式的写出这种关系(比如是这里在使用时调用对方的GetInstance)。
如果在这里依靠语言所提供的便利条件,隐藏两者的依赖关系成为隐式依赖则将留下后患。

隐式依赖不容易被代码维护者发觉和感受到,等到代码中有多处相关联的隐式依赖时,为了修复某问题而调整两对象的先后顺序不经意的破坏了另一对隐式依赖关系,而且由于是隐式的关联,编译器也无法提示你。这样修复一个问题而创造另一个问题的情况在我们小组称为按下葫芦弹起瓢:)

如果所有的依赖关系都是显式依赖,那么使得任何一个代码维护者在修改某处代码时必然要考虑到调整顺序的影响。一旦破坏了其它的依赖关系,编译器首先就会通知你编译失败。于是问题立即暴露。使得维护者回到从全局上解决问题的局面。

于是,潜在的bug不会被轻易的签入到代码仓库。

45

主题

157

帖子

169

积分

注册会员

Rank: 2

积分
169
QQ
 楼主| 发表于 2009-11-20 14:22:00 | 显示全部楼层

Re: Re:如何保证一个对象最先构造,最后析构?

kaikai: Re:如何保证一个对象最先构造,最后析构?

之所以希望在某时间之前让某对象存在,是因为存在一种依赖关系。
那么既然有依赖关系,就应当显式的写出这...

这个不会是隐式的啊,因为你要获得我的支持,必须有我的一个成员,这就像两家公司需要合作一样,如果你要我出资支持你,那么你的公司里必须有我的人。这关系很明显啊,也很好解啊!而且一看定义就知道这个类需要那几个类的支持!也很好维护啊。
就像我例子中的CA类,它的定义里有一个CSupporter类型的成员,就知道它需要CSupporter来支持它,如果你没有事先定义CSupporter类,或者没有包括其头文件,编译也会报错啊,这错误也不难查出吧!

30

主题

422

帖子

433

积分

中级会员

Rank: 3Rank: 3

积分
433
发表于 2009-11-20 16:12:00 | 显示全部楼层

Re:如何保证一个对象最先构造,最后析构?

哦, 果然是显式的。我没注意到你之后修改的代码,抱歉。

45

主题

157

帖子

169

积分

注册会员

Rank: 2

积分
169
QQ
 楼主| 发表于 2009-11-20 16:18:00 | 显示全部楼层

Re: Re:如何保证一个对象最先构造,最后析构?

kaikai: Re:如何保证一个对象最先构造,最后析构?

哦, 果然是显式的。我没注意到你之后修改的代码,抱歉。

没关系,其实跟你讨论的同时,也加深了我对C++的理解。后来那个发现也是在跟你讨论的过程中突然悟到的,所以还要说声谢谢呢!

3

主题

263

帖子

267

积分

中级会员

Rank: 3Rank: 3

积分
267
发表于 2009-12-5 13:08:00 | 显示全部楼层

Re:如何保证一个对象最先构造,最后析构?

1.把构造权限下放给最终用户.并强制用户先构造被依赖对象.否则报错.

template<t>
class Singleton
{
public:
  static t &GetInstance()
  {
       如果ms_singleton为空则抛出异常.
       return *ms_singleton;
  }
   ...
private:
static T* ms_singleton;
};

比如 class supporter : public singleton<supporter>;
用户必须先 new 出 supporter,才能使用其他对象,否则其他对象在引用supporter时报错.

2.把support声明为全局静态对象.如果依赖他的对象是局部对象,没有问题.如果是静态对象,那么问题就变成了静态对象的初始化顺序问题.使用praga init_seg确实不好,我在网上看到另一个办法,就是把全局对象的声明放到同一个公共的头文件里面,按顺序.虽然C++标准没有定义各个文件内的静态对象的构造和析构顺序,但是在同一个文件内声明的对象先声明的会先构造.这个方法还没有试过..

3.使用singleton懒惰初始化方式,并用智能指针代替裸指针.并且依赖supporter的对象内部保存一个supporter的智能指针,这个原理跟楼主的类似啦.

问题是如果你的对象是面向其他开发使用者的时候,而不只是你自己用,那么用户的对象依赖你的supporter时,还是要强制用户自己的对象也得保存一个智能指针.

拿楼主的类举例:
如果其他人用你的类库,他的一个类依赖你的支持者,那么他自己写的类里面必须有一个你的CSupporter成员.
个人感觉这样的限制有时候更繁琐,不如第一种,一次性搞定,用户只需要在最开始构造CSupporter,最后删除他就行.
拿OGRE举例,我只要在一开始就new一个Ogre::Root,以后我的引用都是合法的.我保证在最后把Ogre::Root给delete掉就可以.

当然如果你的CSupporter只是供自己内部调用就没有这个问题了,自己的类里面有一个CSupporter成员来保证初始化顺序,别人用的时候就不用管这些了.呵呵.

2

主题

19

帖子

19

积分

新手上路

Rank: 1

积分
19
发表于 2009-12-22 12:38:00 | 显示全部楼层

Re: 如何保证一个对象最先构造,最后析构?

void main(){
Obj *o1=new Obj;
Obj *o2=new Obj;
Obj *o3=new Obj;
{
do what you want
}
delete o1;
delete o2;
delete o3;
}
[em19]

1

主题

14

帖子

26

积分

注册会员

Rank: 2

积分
26
发表于 2009-12-22 18:29:00 | 显示全部楼层

Re:如何保证一个对象最先构造,最后析构?

我有个相同的问题,但是是一个很实在的问题,看来之前的回复觉得都无法解决,在这里抛出来给大家分析看看:
要是我程序都已经写好了,但目前需要重载new和delete操作符去使用内存池来管理内存,在不改动原来程序的情况下,增加一个内存池管理类,那么如何保证这个内存池管理类的对象是在原来程序所有对象构造之前构造,析构之后析构呢?这个程序里面可能有全局对象,可能有静态对象,怎么保证这个内存管理类对象能够在最先构造最后析构呢?楼主说的方法是不可行的,因为要使用new和delete要跟没有重载之前一样,而使用singleton也不可行,因为并不能保证没有其他singleton在这之前使用,请问各位还有没什么好的建议?

30

主题

422

帖子

433

积分

中级会员

Rank: 3Rank: 3

积分
433
发表于 2009-12-22 23:35:00 | 显示全部楼层

Re: Re:如何保证一个对象最先构造,最后析构?

answerear: Re:如何保证一个对象最先构造,最后析构?

我有个相同的问题,但是是一个很实在的问题,看来之前的回复觉得都无法解决,在这里抛出来给大家分析看看:...


你这个问题大部分情况下用1楼的方法可以解决。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-6-1 11:42

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表