2013-07-20 45 views
0

嗨在这个问题中,我读到编译顺序并不重要,但我真的很奇怪的情况。C++ Makefile编译顺序

我在文件CCSizePolicy.cpp 几个全局变量,就像这样:

const CCSizePolicy CCSizePolicyWrapContent (Const::WRAP_CONTENT); 
const CCSizePolicy CCSizePolicyMatchContent (Const::MATCH_PARENT); 
const CCSizePolicy CCSizePolicyZero (Policy::SP, 0); 

在头

enum Const 
    { 
     WRAP_CONTENT = -1, MATCH_PARENT = -2 
    }; 

extern const CCSizePolicy CCSizePolicyWrapContent; 
extern const CCSizePolicy CCSizePolicyMatchContent; 
extern const CCSizePolicy CCSizePolicyZero; 
在CCLayoutParams.h

extern const CCLayoutParams CCLayoutParamsMatchMatch; 
extern const CCLayoutParams CCLayoutParamsWrapWrap; 
extern const CCLayoutParams CCLayoutParamsMatchWrap; 
extern const CCLayoutParams CCLayoutParamsWrapMatch; 

和CCLayoutParams

还.cpp

const CCLayoutParams CCLayoutParamsMatchMatch (CCSizePolicyMatchContent, 
     CCSizePolicyMatchContent); 

const CCLayoutParams CCLayoutParamsWrapWrap (CCSizePolicyWrapContent, 
     CCSizePolicyWrapContent); 

const CCLayoutParams CCLayoutParamsMatchWrap (CCSizePolicyMatchContent, 
     CCSizePolicyWrapContent); 

const CCLayoutParams CCLayoutParamsWrapMatch (CCSizePolicyWrapContent, 
     CCSizePolicyMatchContent); 

所以,当我在程序中使用他们,我叫CCLayoutParamsWrapWrap.getWidth()和CCLayoutParamsWrapWrap.getHeight()

这应该输出我-1 -1 但我有0 0 ...

秩序生成文件看起来是这样的:

src/view/layout/CCLayoutParams.cpp\ 
... 
src/view/CCSizePolicy.cpp\ 

当我将其更改为

src/view/CCSizePolicy.cpp\ 
src/view/layout/CCLayoutParams.cpp\ 
... 

一切开始工作(我得到-1 -1)发生了什么事?

进出口使用的Linux使用gcc版本4.6.3(Ubuntu的/ Linaro的4.6.3-1ubuntu5)

我的整个项目窃听我不知道为什么,因为我的名字我的源文件进行排序?!? !

回答

2

最有可能的是,这不是文件编译的顺序,而是实际上它们被链接的顺序(它是由你有源的顺序来定义的,我期望) - g ++“收集”变量的全局初始化在链接阶段,然后按照它们被发现的顺序进行处理。然而,这恰好是“观察到的行为”。C++中不同编译单元之间的初始化是未定义的。你不能依赖它以某种方式,绝对没有任何东西阻止g ++改变它放置全局初始化的顺序,以便它以相反顺序而不是当前顺序完成(因为这会使链接过程更快或者其他一些聪明的理由 - 或者只是“觉得”),他们甚至不必告诉你他们已经这么做了。因此,基本上,如果你有全局对象,那么你必须把它们放到一个单独的源文件(“globalobjects.cpp”或其他)中,以使它们按照定义的顺序初始化,或者不依赖于一个在另一个之前被初始化。或者依赖于模糊的定义,即“只要我按照正确的顺序将文件放入正确的位置,链接器就按照正确的顺序执行操作”。

+0

将它们放入.h文件是不错的解决方案吗?类似于const CCLinearLayoutParams CCLinearLayoutParamsMatchMatch( \t CCSizePolicyMatchContent,CCSizePolicyMatchContent); 我将.cpp中的定义移动到h并删除了声明(使用extern) –

+0

不,但如果您按照Steve Jessop的建议使用'constexpr',也许。 –

2

未指定不同源文件中全局变量的初始化顺序。因此,它可以依赖于任何东西,包括例如文件被编译的顺序。

在这种情况下,如果CCLayoutParamsWrapWrapCCSizePolicyWrapContent之前进行初始化,那么它的构造不会看到的CCSizePolicyWrapContent构造函数设置的值-1。它会看到由所谓的“静态初始化”设置的值0,该值在“动态初始化”(即构造函数调用)之前发生。

我不明白gcc是如何引起差异的,但我怀疑它是链接顺序而不是真正重要的编译顺序。但这只是一个猜测,如果你关心确认或反驳它,你可以测试。重要的一点是你不应该依赖它,因为它不需要这样做。

在C++ 11中我认为你可以通过确保CCSizePolicyWrapContent是一个constexpr对象和constexpr构造函数来解决这个问题。否则,你应该阅读“静态初始化顺序失败”,以及各种可用于限制初始化顺序的技术,然后选择一个适合你的环境的技术。