2016-10-26 1 views
18

내가 utilA.cpp에 다음 코드를해야합니다 : utilA.h 라인 0에 struct tm을 사용하고 있기 때문에이 보인다왜 C++의 forward 선언입니까?

error: variable 'xm::tm time1' has initializer but incomplete type 

utilA.cpp를 컴파일 할 때 GCC는 불평
// utilB.h 
namespace xm 
{ 
    void zoo(struct tm timeval); //<-----line 0 
} 


// utilA.cpp 
#include <utilB.h>     //<----line 1 
#include <time.h>     //<----line 2 
namespace xm 
{ 
    void foo() 
    { 
     struct tm time1 = {0}; //<----line 3 
    } 
} 

, 그러나 time.h을 포함하지 않고 컴파일러는 라인 0에있는 struct tm을 전달 선언으로 처리하므로 라인 2의 struct tm은 라인 0의 헤더 안에 xm::tm으로 처리됩니다.

그래서 C++ 표준은 forward 선언과 같은 함수 매개 변수 유형으로이 struct tm을 정의합니까? 이것을 설명하는 데 도움이되고 표준의 인용문이 도움이 될 것입니다.

+6

헤더가 헤더에 달려 있으므로 헤더에'#include '을 써라. – molbdnilo

+0

예, utilB.h에 #include 을 추가해야하지만, 거대한 프로젝트의 코드 스 니펫이기 때문에 근본 원인을 찾기 전에 많은 혼란을 겪습니다. – ZijingWu

+0

이것은 매우 나쁜 프로그래밍 스타일입니다. 무시해. 추신 : 당신은'# include'-s를 맨 위로 옮기려고 했습니까? – i486

답변

20

0 행에서 이라는 클래스를 xm 네임 스페이스 안에 선언했습니다. 예, C++에서는 함수/템플릿 매개 변수에서 유형을 선언 할 수 있습니다.

N4140 는 형 지정자 정교가 도입되면 §는 3.4.4 [basic.lookup.elab/2

클래스 키 및 룩업 a를 찾지 이전에 타입 이름를 선언하거나 는 형 지정자를 정교 경우는 양식 선언에 나타납니다

클래스 애 y 속성 지정자 - seq opt 식별자;

정교 유형 지정자은 3.3.2에서 설명한대로 클래스 이름을 소개하는 선언입니다. 당신이 xm 네임 스페이스 내에서 tm라는 이름의 클래스를 선언하기 때문에

, 그것은 간주되지 않습니다 이름 조회 라인 3. ::tm (및 ::std::tm)에 tm에 대한 발견 한 첫 번째 이름입니다. 그리고 클래스 ::xm::tm의 정의가 없으므로 컴파일러는 불완전한 유형이라는 것에 대해 불평합니다. 당신은 C++에서 C 코드를 작성하지 않은 경우

, 당신은 1

struct tm; 

namespace xz{ 
    void zoo(tm timeval); 
} 

또는

#include <ctime> 

namespace xz{ 
    void zoo(tm timeval); 
} 

같은 것을 써서 당신은 그런 문제가 없다.

1 당신이 std 네임 스페이스에 이름을 앞으로 선언 할 수 없습니다 기억

7

그래서 C++ 표준은 앞으로 선언과 같은 함수 매개 변수의 유형으로이 struct tm을 정의한다. 이것을 설명하는 데 도움이되고 표준의 할당량이 도움이 될 것입니다.

예, struct tm timeval은 여기에 새로운 클래스 이름 xm::tm을 소개합니다.


(설명과 따옴표)

struct tm 새로운 클래스 이름을 소개하는 데 사용할 수있는 elaborated type specifier입니다.

$3.1/4 Declarations and definitions [basic.def]

[참고

: 클래스 이름이 암시 정교 형 지정자로 선언 될 수있다 ([dcl.type.elab). - 최종 주]

$9.1/2 Class names [class.name] :

클래스 키 식별자만으로 이루어진 선언; 현재 범위에서 이름의 재 선언 또는 식별자의 클래스 이름으로 전달 입니다. 현재 범위에 클래스 이름을 소개합니다.

$3.4.4/2 Elaborated type specifiers [basic.lookup.elab] : 정교 형 지정자는 양식 선언에 나타나는 경우

또는

가 :

class-key attribute-specifier-seqopt identifier ; 

정교 형 지정자가 소개하는 선언입니다 [basic.scope.pdecl]에서 설명한대로 클래스 이름.

$3.3.2/7 Point of declaration [basic.scope.pdecl] :

정교 형 지정자 상기에서 않거나 계산 지정자-SEQ 또는 공간 범위에 정의 된 함수의 변수 선언 절을 사용한 경우, 식별자는 선언 네임 스페이스의 클래스 이름으로 에 선언이 포함되어 있습니다. 함수 매개 변수 선언으로서 사용 struct tm timeval 들어

, <time.h> 포함 전류 범위 (즉, 공간 xm)에서 선언 될 tm라는 어떠한 클래스 클래스 tm 여전히 없다되지 않기 때문에이 후 xm::tm 앞으로 선언한다.