보통 C++을 공부할 때 클래스를 배우게 되면 클래스의 정의와 구현 부분을 아래와 같이 분리하라고 배우게 됩니다.

 A.h

A.cpp

 그런데 템플릿 프로그래밍으로 넘어오게 되면 위와 같은 방식으로 클래스를 나누었을 때 링크 에러가 나타나게 됩니다.

A.h

 A.cpp

위와 같이 코드를 작성하면 빌드 시 링크 에러가 납니다.

보통 사람들은 “템플릿은 컴파일 타임에 모든것이 준비되어야 하므로 헤더 안에 구현까지 들어있어야 한다”고 얘기합니다. 그런데 반은 맞고 반은 틀린 말입니다. 꼭 구현까지 들어있을 필요는 없습니다. 아래와 같은 방법으로 해결할 수 있습니다.

 A.h

 A.hpp

C++에서는 템플릿도 정의와 구현을 나눌 수 있도록 hpp라는 파일 확장자를 지원합니다. 보통 IDE에선 헤더 파일로 인식합니다. 위와 같이 “클래스명.h”의 #endif 전처리 바로 앞에 #include 전처리를 이용하여 포함시키면 됩니다.

 

만약 “난 죽어도 정의와 구현을 한 파일 안에 담아두고 싶다”는 생각을 가진 분이 있다면 아래와 같이 해주면 됩니다.

 A.h

차이점을 아시겠나요? 전 이 해결법으로 인해 #include 전처리를 확실히 이해하게 되었습니다. #include는 해당 파일의 내용을 그냥 전처리 단계에서 때려박아버립니다. 우리가 마르고 닳도록 쓰던 <stdio.h>나 <iostream> 헤더도 사실은 컴파일 단계에선 우리의 프로그램 코드 맨 앞에 해당 헤더의 모든 것이 들어가게 되는 겁니다.


 

사실 단계까지 왔으면 #ifndef-#define-#endif를 써야하는 이유를 아시겠지만 혹시나 해서 덧붙여 설명해드리자면, 방금 말한것처럼 #include는 헤더 혹은 파일의 모든 내용을 박아버리는데 우리가 만든 여러 헤더 파일에서 특정 헤더를 다들 #include로 포함했다면 중복 포함이 생겨 컴파일 시에 오류가 발생할 수 있습니다. 보통 이것을 해결하는 방법이 두 가지입니다.

첫 번째는 #pragma 키워드를 이용하는 방법입니다. 컴파일 시 전처리 단계에서 위와 같은 코드를 만나면 한 번만 포함하고 건너뛰게 됩니다.

두 번째는 방금 말한 #ifndef-#define-#endif 키워드를 이용하는 방법입니다. 이것은 #define을 통한 정의가 되어 있지 않으면 내용을 포함시키고, 이미 되어있으면 건너뛰도록 하는 방법으로 중복 포함을 방지합니다.

One thought on “[C++] 템플릿 클래스의 정의와 구현을 분리하는 방법 & 헤더 중복 포함 방지하기

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.