2013-07-20 5 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 ...

порядок в Makefile выглядит следующим образом:

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

, когда я изменить его на

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

Все начинает работать (я получаю -1 -1), что происходит?

Im используя Linux с GCC версии 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)

Весь мой проект прослушивается я не знаю, почему, потому что я сортировать мои исходные файлы по имени ??!? !

ответ

2

Скорее всего, это не тот порядок, в котором файлы COMPILED, но на самом деле они связаны LINKED (что определяется порядком, в котором у вас есть ваши источники, я ожидаю) - g ++ «собирает» глобальную инициализацию переменных на этапе связывания, и затем они обрабатываются в том порядке, в котором они были найдены. Однако это просто «наблюдаемое поведение».Инициализация между различными единицами компиляции в C++ не определена. Вы не должны полагаться на то, что это так или иначе, абсолютно ничего не мешает g ++ изменять порядок, в который он помещает глобальную инициализацию, чтобы он выполнялся в обратном порядке, а не в текущем порядке (потому что это ускоряет процесс ссылки , или какая-то другая умная причина - или просто «чувствовала себя так»), - и им даже не пришлось бы говорить вам, что они это сделали.

Таким образом, если у вас есть глобальные объекты, вы должны либо поместить их в один исходный файл («globalobjects.cpp», либо какой-либо такой), чтобы заставить их инициализировать в определенном порядке или не полагаться на один из которых инициализируется перед другим. Или полагаться на неопределенное определение, что «в настоящее время компоновщик делает вещи в правильном порядке, пока я помещаю свои файлы в правильном порядке».

+0

Это хорошее решение, чтобы поместить их в файл .h? что-то вроде const CCLinearLayoutParams CCLinearLayoutParamsMatchMatch ( \t CCSizePolicyMatchContent, CCSizePolicyMatchContent); Перемещение определения с .cpp на h и удаление объявления (с extern) –

+0

Нет, но если вы используете 'constexpr', как полагает Стив Джессоп, возможно. –

2

Порядок инициализации глобалов в разных исходных файлах не указан. Как таковой он может зависеть от чего угодно, включая, например, порядок, с которым файлы компилируются.

В этом случае, если CCLayoutParamsWrapWrap инициализируется перед CCSizePolicyWrapContent, то его конструктор не будет видеть значение -1, установленный конструктором CCSizePolicyWrapContent. Вместо этого он увидит значение 0, заданное так называемой «статической инициализацией», которое происходит до «динамической инициализации» (то есть вызовов конструктора).

Я не знаю конкретно, что о gcc вызывает разницу, но я подозреваю, что это скорее порядок ссылок, чем порядок компиляции, который действительно имеет значение. Это только предположение, хотя, если вы хотите подтвердить или опровергнуть это, вы можете проверить. Важным моментом является то, что вы не должны полагаться на него, так как от него не требуется вести себя так.

В C++ 11 Я думаю, вы могли бы исправить это, убедившись, что CCSizePolicyWrapContent является объектом constexpr с конструктором constexpr. В противном случае вы должны прочитать о «статическом фиаско порядка инициализации» и о различных методах, доступных для ограничения ограничений на порядок инициализации, а затем выбрать тот, который соответствует вашим обстоятельствам.

Смежные вопросы