2012-09-07 1 views
2

필자는 전에 여러 번 포함 된 가드를 사용해 왔지만 실제로 작동하는 방법이나 이유를 결코 이해하지 못했습니다.C++ 포함 가드가 작동하지 않는 것으로 보입니까?

왜 다음 작동하지 않습니까?

#ifndef CAMERA_CLASS_HPP 
#define CAMERA_CLASS_HPP 


class camera_class 
{ 
.... 
}; 

camera_class glcam = camera_class(); 


#endif // CAMERA_CLASS_HPP 

오류는 이것이다 :, 또한

-------------- Build: Debug in System --------------- 

Linking console executable: bin/Debug/System 
/usr/bin/ld: error: obj/Debug/main.o: multiple definition of 'glcam' 
/usr/bin/ld: obj/Debug/camera_class.o: previous definition here 
/usr/bin/ld: error: obj/Debug/main.glfunc.o: multiple definition of 'glcam' 
/usr/bin/ld: obj/Debug/camera_class.o: previous definition here 
collect2: ld returned 1 exit status 
Process terminated with status 1 (0 minutes, 0 seconds) 
0 errors, 0 warnings 

(! 당신은 아마이 질문의 제목부터가 될 것 무엇을 추측 할 수있다) 사람이 왜 헤더 가드 작품 나에게 설명해주십시오 수 ?

+1

이해. 헤더 파일이 동일한 소스 파일 *에 두 번 포함되지 않도록합니다. 그들은 헤더가 다른 소스 파일에 두 번 포함되지 않도록하지도 못합니다. – john

+0

감사합니다 존, 나는 그 근본적인 차이를 이해하지 못했습니다! – user3728501

답변

2

여러 위치에서 사용할 수있는 glcam 개체를 하나 만들고 싶습니다. 나는 static 인스턴스를 반환하는 무료 함수를 노출함으로써 그렇게 할 것입니다. 이것은 extern을 사용하는 것과 비슷하지만, 의도적으로 조금 더 명확하게 나타납니다.

#ifndef CAMERA_CLASS_HPP 
#define CAMERA_CLASS_HPP 


class camera_class 
{ 
.... 
}; 

camera_class& get_camera(); 


#endif // CAMERA_CLASS_HPP 

// in the CPP 

camera_class& get_camera() 
{ 
    static camera_class the_camera; 
    return the_camera; 
} 

이 당신에게 extern에 의존하지 않고 하나의 camera_class 인스턴스를 사용할 수있는 기능을 제공하지만, 코드의 다른 영역을 만들 무료로 동시에 싱글로 사용하도록 강요하지 않습니다 자신의 비공개 인스턴스도 포함합니다.

camera_class의 멤버 함수 (자유 함수) 또는 static 멤버 함수로 구현할 수 있습니다.

당신이 중 하나 회원으로 또는 비 친구 비회원으로 구현할 수있는 기능을 작성하는 경우, 당신이 선호한다 : 나는 스콧 마이어스에서 몇 가지 훌륭한 조언에 따라, 전자를 선택했다 을 비회원 기능으로 구현하십시오.

출처 : 경비원 할 착각 포함 무엇 http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197

+0

아, 이것은 영리한 솔루션, 감사합니다 차드! – user3728501

+0

... 또 다른 질문이지만. 왜'camera_class & get_camera();'가 클래스 내부의 메소드가 아닌가? 클래스 정의를 벗어나는 이유는 무엇입니까? – user3728501

+0

위대한 질문과 의견에 보이는 것보다 눈에 잘 띄는 장소에서 대답할만한 가치가 있습니다. 내 대답의 마지막 단락을보십시오. 이 링크에는 원래 질문에 대한 주제와 관련된 훌륭한 정보가 있습니다. – Chad

4

근본 원인은 :
헤더 가드 같은 translation unit에 있지만 서로 다른 번역 단위에서 동일한 헤더를 여러 번의 포함을 방지 할 수 있습니다. 여러 개의 번역 단위에 동일한 헤더 파일을 포함하면
헤더를 포함하는 모든 번역 단위에 glcam 사본이 실제로 생성됩니다.
C++ 표준 각각의 기호는 defined 한 번만 할 수 있습니다 의무 (One Definition Rule) 따라서 링커 문제를 당신에게 오류입니다.

솔루션 :
헤더 파일에 glcam을 만들지 마십시오. 대신 그것은 단지 한 번만 정의되는 방식으로 만들어 져야합니다. 이렇게하는 올바른 방법은 using the keyword extern입니다.

+0

어디에서'glcam'을 만들어야합니까? .cpp 파일로 만들어야합니까? – user3728501

+0

@EdwardBird : 쿼리에 응답하도록 업데이트되었습니다. –

+0

'extern'이 작동하지만, 나는 그 사실을 조금 혼란스럽게 생각합니다. 나는 기본적으로 동일한 결과를 얻는 나의 대답에 제공된 방법을 사용하는 것을 선호하지만, 나는 더 명확하게 발견한다. 분명히 이것은 맛의 문제 일뿐입니다. – Chad

7

헤더 가드는 단일 변환 단위에서 다중 포함을 방지합니다. 헤더는 복수의 변환 단위 (및 임)이 포함되어있다 :

// a.cpp: 
#include "camera.hpp" 

// b.cpp 
#include "camera.hpp" 

이것이 a.objb.obj 각각 glcam에 대한 정의를 포함하는 생성한다. 최종 바이너리를 생성하기 위해 함께 링크되면 다중 정의 오류가 발생합니다.

당신은 헤더에glcam.cpp 파일에 정확히 한 번만에게 그것을 정의 선언 해야합니다

// camera.hpp 
... 

extern camera_class glcam; 

// camera.cpp 
#include "camera.hpp" 

camera_class glcam; 
+0

이것은 내가 선택한 해결책입니다. 완전히 다른 파일 ('main.opengl.cpp')에'camera_class'의 객체를 가지고있는 것을 좋아하지 않지만해야 할 것입니다! – user3728501

1

가드가 하나의 컴파일에 귀하의 헤더에있는 텍스트의 여러 인스턴스를 방지 포함 유닛 (예 : .o로 빌드되는 단일 .cpp)

여러 텍스트가 여러 컴파일 단위에 나타나지 않도록합니다.

그래서 링크 타임이 헤더를 포함하는 각각의 편집 장치는 기호로

camera_class glcam = camera_class(); 

있다. C++은 "glcam"을 참조 할 때 결정할 수있는 단일 전역 정의를 결정할 수 없습니다.main.o 또는 camera_class.o의 카메라 하나? 여러 파일에서이 파일을 포함하고 있기 때문에

2

, 당신은 One Definition Rule 깨고있다 : 전체 프로그램에서

를, 객체 또는 인라인이 아닌 기능 더 정의 하나보다

을 가질 수 없습니다

glcam 정의를 헤더 파일이 아닌 소스 파일에 넣거나 대신 extern으로 선언하고 일부 소스 파일에 정의를 제공해야합니다.

0

각 소스 파일에 하나의 정의 만 나타납니다.

문제는 여러 소스 파일이 있고 링커에서 여러 정의를 찾는 것입니다. 헤더 파일에서

당신은 넣어해야합니다

extern camera_class glcam; 

그리고 하나와 하나의 소스 파일을 넣어 머리글에서이 무엇을 사용 :

camera_class glcam = camera_class(); 

이 시점 당신 '에서 초기화 순서 문제를 알아야합니다. 모든 정적 개체에서 glcam을 사용하지 마십시오.