这是我在百度知道上的问题:
程序中有一个对象是对象必需依赖的,如何保证这个被依赖的对象在所有依赖它的对象构造之前构造,析构之后析构后呢,C++语言好像没有强制规定全局对象的构造与析构顺序,求不依赖特定实现平台的解决方案,肯请大师们多多赐教!

以下是热心人的回答:
不用可以去关注。
如果它是对象是全局的,那么反正不析构。如果是局部的,那么其他跟他相关的对象也是局部的,那么在析构时,他们会自动优先被析构。如果相关对象为全局的,那么是你的数据结构有问题,要重新架构
回答者:曹糯糯 - 举人 四级 2009-11-17 00:43

我不太明白你的意思,这看上去像个非常简单的问题.
把对象定义为全局.
编译器先为全局对象分配内存空间.然后主线程进入main()或者WinMain()函数开始执行.
#includelt;iostreamgt;
Class A ;
Class B ;
int main()
{
Class C ;
}
B 和 C都可以很安全的使用A 作为它的成员.
回答者: jackheroes8383 - 助理 四级 2009-11-17 01:00

看来你的题有个问题没有搞懂,就是什么叫做“有一个对象是其他对象必需依赖的 ”
说清楚这里估计能够解决
回答者: keepingdo - 中级 二级 2009-11-17 01:01

使用一个类做全局变量,它只管构造和析构其他的类的实例。
用全局指针来管理。
class A{...};
clase B{...};
clase C{...};
A * a1;
B * b1;
C * c1;
class Manage {
public:
Manage(){
a1 = new A();
b1 = new B();
c1 = new C();
}
virtual ~Manage()
{
delete c1;
delete b1;
delete a1;
}
};
Manage g_manage;
可以保证 a1 在 b1 之前构造,之后析构。
如果指针用的不爽,可以用引用
A amp; aa1 = *a1;
g_manage是全局变量,所以程序启动时构造,
结束时析构。不信可以加断点跟踪。
回答者: Laplas - 江湖豪侠 九级 2009-11-17 01:34

其实不用关注,编译时会查出错误。
你愿意,可以用宏
#ifndef CLASS_BAS //如果没有声明 Class BAS
Class BAS;
#define CLASS_BAS
#endif
#ifdef CLASS_BAS //如果 声明 了 Class BAS
CLASS C;// 则声明C;
CLASS D;// 则声明D;
#endif
可以用宏描述C 已deleted, D 已deleted
#ifndef C_deleted
delete C
#define C_deleted
#endif
#ifndef D_deleted
delete D
#define D_deleted
#endif
#ifdef C_deleted
#ifdef D_deleted
delete BAS
#endif
#endif
回答者:L_o_o_n_i_e - 首席运营官 十五级 2009-11-17 05:56

在同一编译单元里, 最先定义的全局对象最先构造, 最后析构, 这是确定的
问题是不同编译单元之间的对象构造和析构顺序是不确定的
如果这个顺序真的很重要的话(实际上我很怀疑。。) , 你可以吧所有全局对象在同一个.cpp中定义, 在文件里只用 extern
回答者: vbtraz - 下位魔导师 十一级 2009-11-17 09:32

以下是我回复:
很感谢大家的热心帮助,不过你们的回答都不太理想,分述如下:
to曹糯糯:如果是一个库的初始化呢?不能不关注吧!
to jackheroes8383:因为C++标准没有强制规定全局对象的构造顺序,所以你的方法不把稳。
to keepingdo:就是初始化只需要一次,并且是在程序开始的时侯初始化,程序的最后析构,所以一般把它们定义为全局变量,并且类中用一个静态成员保证其初始化过程只进行一次,但问题是,必须保证它的初始化在那些依赖它的对象构造之前,它的析构在那些依赖它的对象析构之后,你不能限定这些对象不能定义为全局的,因为这个类不是只提供你个人使用,而C++又没强制规定了全局对象的构造和析构顺序,通常都是按照声明的顺序进行构造,相反的顺序析构,但不保证不会出现例外情况。
to Laplas: 你的方法倒是可以,但问题是我现在不知道那些类的定义,等我知道了,我的代码已经木已成舟,所以你的方法也行不通。
to L_o_o_n_i_e:你的方法不太理解。
to vbtraz: 问题就是我不是这个类的使用者,而我也不想给客户太多限制,那会让人很不爽。

以下是我的解决:
最后大家来看看我的解决方案,评一下优缺点吧!点评好的我会再加分的。
//支持者
class CSupporter
{
public:
CSupporter(){if(NULL==m_pUS)m_pUS=new UserSupporter;}
~CSupporter()
{
if(NULL!=m_pUSamp;amp;0==--m_pUS-gt;m_UserCount)
{
delete m_pUS;
m_pUS=NULL;
}
}
CSupporter(const CSupporteramp; src){if(NULL!=m_pUS)++m_pUS-gt;m_UserCount;}
CSupporteramp; operator=(const CSupporteramp; src){return *this;}
private:
struct UserSupporter
{
long m_UserCount;
UserSupporter():m_UserCount(1){coutlt;lt;quot;构造支持者quot;lt;lt;(unsigned long)thislt;lt;quot;!quot;lt;lt;endl;}
~UserSupporter(){coutlt;lt;quot;析构支持者quot;lt;lt;(unsigned long)thislt;lt;quot;!quot;lt;lt;endl;}
};
static UserSupporter* m_pUS;
};
CSupporter::UserSupporter* CSupporter::m_pUS=NULL;

//用户类
class CA
{
public:
CA(const CSupporteramp; Supporter):m_Supporter(Supporter)
{coutlt;lt;quot;构造CA对象quot;lt;lt;(unsigned long)thislt;lt;quot;!quot;lt;lt;endl;}
~CA(){coutlt;lt;quot;析构CA对象quot;lt;lt;(unsigned long)thislt;lt;quot;!quot;lt;lt;endl;}
private:
CSupporter m_Supporter;
};
class CB
{
public:
CB(const CSupporteramp; Supporter):m_Supporter(Supporter)
{coutlt;lt;quot;构造CB对象quot;lt;lt;(unsigned long)thislt;lt;quot;!quot;lt;lt;endl;}
~CB(){coutlt;lt;quot;析构CB对象quot;lt;lt;(unsigned long)thislt;lt;quot;!quot;lt;lt;endl;}
private:
CSupporter m_Supporter;
};
class CC
{
public:
CC(const CSupporteramp; Supporter):m_Supporter(Supporter)
{coutlt;lt;quot;构造CC对象quot;lt;lt;(unsigned long)thislt;lt;quot;!quot;lt;lt;endl;}
~CC(){coutlt;lt;quot;析构CC对象quot;lt;lt;(unsigned long)thislt;lt;quot;!quot;lt;lt;endl;}
private:
CSupporter m_Supporter;
};
class CD
{
public:
CD(const CSupporteramp; Supporter):m_Supporter(Supporter)
{coutlt;lt;quot;构造CD对象quot;lt;lt;(unsigned long)thislt;lt;quot;!quot;lt;lt;endl;}
~CD(){coutlt;lt;quot;析构CD对象quot;lt;lt;(unsigned long)thislt;lt;quot;!quot;lt;lt;endl;}
private:
CSupporter m_Supporter;
};

int main()
{
//为了使输出都能看得见,测试我放在了main()函数内。
CSupporter supporter1, supporter2;
CA a1(supporter1), a2(supporter2);
CB b1(supporter1), b2(supporter2);
CD d1(supporter1), d2(supporter2);
CC c1(supporter1), c2(supporter2);
a1=a2;
c2=c1;
return 0;
}

主要思想:通过引用计数保证CSupporter对象在所有依赖它的对象析构之后析构,通过静态成员保证唯一实例,并且只初始化一次,通过限制用户类的构造函数参数里必须有一个CSupporter类型的参数,保证了在构造用户类对象之前必须先有一个CSupporter实例存在。

结果:
构造支持者11468864!
构造CA对象1244984!
构造CA对象1244980!
构造CB对象1244976!
构造CB对象1244972!
构造CD对象1244968!
构造CD对象1244964!
构造CC对象1244960!
构造CC对象1244956!
析构CC对象1244956!
析构CC对象1244960!
析构CD对象1244964!
析构CD对象1244968!
析构CB对象1244972!
析构CB对象1244976!
析构CA对象1244980!
析构CA对象1244984!
析构支持者11468864!
Press any key to continue
锐亚教育

锐亚教育,游戏开发论坛|游戏制作人|游戏策划|游戏开发|独立游戏|游戏产业|游戏研发|游戏运营| unity|unity3d|unity3d官网|unity3d 教程|金融帝国3|8k8k8k|mcafee8.5i|游戏蛮牛|蛮牛 unity|蛮牛