嗨,在这个问题中,我读到编译顺序无关紧要,但我的情况真的很奇怪。
我在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()和CCLayoutParams WrapWrappe.getHeight()
这应该输出me-1-1但是我有0 0…
makefile中的订单如下:
src/view/layout/CCLayoutParams.cpp
...
src/view/CCSizePolicy.cpp
当我把它改成时
src/view/CCSizePolicy.cpp
src/view/layout/CCLayoutParams.cpp
...
一切都开始工作了(我得到-1-1)发生了什么?
我使用带有gcc版本4.6.3的Linux(Ubuntu/Linaro 4.6.3-1ubuntu5)
我的整个项目都被窃听了,我不知道为什么,因为我按名称对源文件进行排序??!?!
很可能,这不是文件编译的顺序,而是它们链接的顺序(我想这是由你的源所在的顺序定义的)-g++"收集"链接阶段变量的全局初始化,然后按照找到它们的顺序处理它们。然而,这恰好是"观察到的行为"。C++中不同编译单元之间的初始化是未定义的。你不能以这样或那样的方式依赖它,绝对没有什么可以阻止g++改变全局初始化的顺序,使其以相反的顺序而不是当前的顺序进行(因为这会使链接过程更快,或者其他一些聪明的原因-或者只是"感觉像这样")-他们甚至不必告诉你他们已经这样做了
所以,基本上,如果你有全局对象,那么你必须把它们放在一个单一的源文件("globalobjects.cpp"或类似的文件)中,使它们按照定义的顺序初始化,或者不依赖于一个在另一个之前初始化。或者依赖于模糊的定义,即"当前,只要我按正确的顺序放置文件,链接器就会按正确的次序进行操作"。
不同源文件中全局变量的初始化顺序未指定。因此,它可以取决于任何事情,例如包括文件的编译顺序。
在这种情况下,如果CCLayoutParamsWrapWrap
在CCSizePolicyWrapContent
之前初始化,则其构造函数将看不到CCSizePolicyWrapContent
的构造函数设置的值-1
。相反,它将看到由所谓的"静态初始化"设置的值0
,该值发生在"动态初始化"(即构造函数调用)之前。
我不知道gcc的具体原因,但我怀疑真正重要的是链接顺序,而不是编译顺序。不过,这只是一个猜测,如果你想证实或反驳它,你可以测试一下。重要的一点是,你不应该依赖它,因为它不需要那样做。
在C++11中,我认为可以通过确保CCSizePolicyWrapContent
是一个具有constexpr
构造函数的constexpr
对象来解决这个问题。否则,您应该阅读有关"静态初始化顺序惨败"的内容,以及可用于对初始化顺序施加约束的各种技术,然后选择适合您情况的技术。