2012-06-06 4 views
0

순환 참조 문제 (예 : A.h 및 B.h # 서로 포함)가 발생했으며 어떤 사람들은 #pragma를 사용하지 못하도록 한 번 조언했습니다. 그러나이 솔루션은 아직 작동하지 않는 것으로 보입니다. 무슨 일이 일어나고#pragma once and #include issues

더 이상 (심지어 A.cpp에서) 아 이외의 파일 인식된다 클래스 A는 동일한는

은 내가 당신에게 코드를 보여 드리죠 클래스 B의 발생 :

#pragma once 
#include "B.h" 

class A { 
public: B* b; 

}; 

BH

#pragma once 
#include "A.h" 

class B { 
    public: A* a; 
}; 

오류 추적 다음으로 판독 동일한 A.cpp

A.cpp

#include "stdafx.h" 
#include "A.h" 
#include "B.h" 

B.cpp이다 :

1> B.cpp 1> c : \ users \ user \ documents \ visual studio 2010 \ projects \ envmodel \ test \ bh (5) : 오류 C2143 : 구문 오류 : ''이 (가) 없습니다. 예 : ''1> c : \ users \ user \ documents \ visual 스튜디오 2010 \ projects \ envmodel \ test \ b.h (5) : 오류 C4430 : 누락 유형 지정자 - int가 가정됩니다. 참고 : C++는 1> c : \ users \ user \ documents \ visual studio 2010 \ projects \ envmodel \ test \ b.h (5)를 지원하지 않습니다. 오류 C4430 : 누락 유형 지정자가 있다고 가정합니다. 참고 : C++은 default-int 1> A.cpp 1> c : \ users \ user \ documents \ visual studio 2010 \ projects \ envmodel \ test \ bh (5)를 지원하지 않습니다. 오류 C2143 : 구문 오류 : 이 없습니다. ';' 예 : ''1> c : \ users \ user \ documents \ visual studio 2010 \ projects \ envmodel \ test \ b.h (5) : 오류 C4430 : 누락 된 형식 지정자가 있다고 가정합니다. 참고 : C++는 1> c : \ users \ user \ documents \ visual studio 2010 \ projects \ envmodel \ test \ b.h (5)를 지원하지 않습니다. 오류 C4430 : 누락 유형 지정자가 있다고 가정합니다. 참고 : C++ 기본-INT 지원하지 않습니다

명확히하기 내가 좋아하는 것 두 가지 더있다 :

  1. 방법 및 Visual Studio 2010 년 #INCLUDE "에 stdafx.h"를 사용하는 경우 (정말이 IDE가 싫지만 C++에서 잘 작동하는 유일한 것으로 보인다 - Netbeans은이 언어로 된 총 휴지통 임)

  2. #pragma once를 올바르게 사용하는 방법은 무엇입니까? 난 그냥 각 파일의 첫 번째 줄에 넣어 것이라고 가정합니다 (글쎄, 분명히 내 문제를 해결하지 못합니다!). 또한 #include "stdafx.h"앞이나 뒤에 삽입해야합니까? 참고 : #pragma를 stdafx.h에 한 번 넣지 않았습니다.

감사합니다.

편집 : 세미콜론을 잊어 버렸기 때문에 원본 오류 추적이 부 풀렸습니다. Edit2 : 포인터를 사용하는 것을 잊어 버렸습니다. 내 실제 프로그램은 일반 객체 값 대신 포인터를 사용 했으므로 작은 예제를 만들기 위해 서두르지 않았다.

+2

클래스 정의 끝에 세미콜론이 필요합니다. – shf301

+1

게시물은 게시물 당 하나의 질문을 가져야합니다. 더 궁금한 점이 있으면 추가 게시물을 작성하십시오. – mydogisbox

+0

헤더 파일의'# ifndef'와'# define' 지시어에 대해 어디에서'#pragma once'를 했습니까? - "각 파일의 첫 번째 줄에 넣었 으면 좋겠다." 그러나'# define' 지시어를 따라 가면 안됩니까? – cmo

답변

9

순환 종속성을 가질 수 없습니다.

이렇게 생각하십시오. 당신이 타입 A의 객체를 instanciate한다면; 얼마나 큰가요? 대답은 무한히 큽니다. 따라서 어쨌든 원형 인 객체는 만들 수 없습니다.

주기를 선택적 값 (포인터)으로 분리해야합니다.
그래서 A에 대한 포인터를 보유하고 앞으로 참조를 사용하도록 B를 변경하면 작동합니다.

#pragma once 
class A; // Forward reference. 

class B { 
    public: A* a; // Break cycle with a pointer. (In real life use a smart pointer) 
} 

참고 : 헤더 파일에는 여전히 #pragma once을 사용해야합니다.

+0

죄송합니다, 그건 감독이었습니다. 전방 참조는 내가 놓친 것입니다. 클래스 A, B, C와 동일한 설정 (A, B, C는 서로 포인터가 있음)으로 접근 해 보았습니다. 내가 이상하다고 생각하는 한 가지 점은 C++은 동일한 네임 스페이스에있는 것들만 정확하게 선언 할 수 있다는 인상을줍니다. 그래서 앞으로 참조하는 트릭이 절대로 나에게 오지 않았습니다. 이걸 상환. –

4

아니요, #pragma once은 순환 포함 문제를 표준 가드보다 더 이상 해결하지 못합니다. 당신이하는 일은 근본적으로 재귀적인 구조이며, sizeof(T) == infinity을 의미하기 때문에 일반 값을 사용하여에 재귀 구조를 사용할 수 없습니다. 해결책은 다음과 같습니다.

  1. A.h에 B.h를 포함하지 않습니다.
  2. B 인스턴스를 A에 보유하는 일반 값 대신 std::unique_ptr (또는 인스턴스를 소유하지 않은 경우 미처리 포인터)을 사용합니다.

또는 그 반대로, 클래스가 실제로 무엇인지에 따라 다릅니다. 물론 가장 좋은 해결책은 디자인 레벨 (리팩터 공통 부품, 그런 종류의 물건)에서 순환 의존성을 완전히 제거하는 것입니다.

stdafx.h은 관련이 없습니다 (이 이름은 단지 규칙 일뿐입니다). "프리 컴파일 된 헤더"를 검색하십시오.