2013-07-20 3 views
0

안녕하세요,이 질문에 나는 컴파일 순서는 중요하지 않지만 정말 이상한 상황이 있습니다.C++ Makefile 컴파일 순서

나는 그들과 같이 파일 CCSizePolicy.cpp 에서 몇 가지 전역 변수가 있습니다

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

헤더에

CCLayoutParams.h

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

및 CCLayoutParams에서 또한

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

extern const CCSizePolicy CCSizePolicyWrapContent; 
extern const CCSizePolicy CCSizePolicyMatchContent; 
extern const CCSizePolicy CCSizePolicyZero; 

.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을 얻습니다) 무슨 일이 벌어지고 있습니까? 내가 이름으로 내 소스 파일을 정렬하기 때문에 내 전체 프로젝트 내가 왜 모르는 도청되는

GCC 버전 4.6.3 (우분투/리나 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에서는 CCSizePolicyWrapContentconstexpr 개체이고, 생성자가 constexpr 인 것을 수정하면 문제를 해결할 수 있다고 생각합니다. 그렇지 않으면 "정적 초기화 순서 실패"및 초기화 순서에 제약 조건을 부과하는 데 사용할 수있는 다양한 기술을 읽은 다음 상황에 맞는 다양한 기술을 선택해야합니다.