|
C를 비롯한 수많은 언어들이 공통적으로 가지고 있으면서, 그리고 프로그래밍 입문 당시부터 보게 되는 include라는 존재가 있다. 주로 다른 파일에서 선언된 함수나 변수, 상수값에 대한 정보를 가지고 있는데, 같은 데이터가 여러 파일에 걸쳐서 사용되는 경우에 유용하게 쓰인다. 프로그래밍을 조금이라도 해본 사람이라면 누구나가 알겠지만, 이것을 사용하는데 있어서 주의하지 않으면 얼마나 많은 시간을 삽질해야 할지 모른다. 한번쯤 눈여겨봐두면 실무를 하다가 언젠가 한번쯤 써먹게 될만한 유용한 것이라 생각되어 또 몇자 적어본다. #include의 역할 hdr1.h 파일
class DummyBase { private: int _i; public: DummyBase(int i): _i(i) { } int Get() { return _i; } void Set(int i) { _i = i; } };
hdr2.h 파일 #include "hdr1.h" // hdr1.h 을 여기서 include 하고 있습니다 class Dummy: DummyBase { public: Dummy(int i): DummyBase(i) { } int operator() () { return Get(); } int operator() (int multi) { return Get() * multi; } }; main.cpp 파일
#include "hdr1.h" // main.cpp 에서도 hdr1.h 을 include 하네요 #include "hdr2.h" int main() { DummyBase db(200); Dummy d(100); } main.cpp 에서 한번포함한 hdr1.h 의 헤더를 또 포함하게 되기때문에 에러를 내게된다 헤더파일의 중복정의 방지 비록 파일은 분리되어 있어도 인클루드하게 되는 헤더파일의 내용들은 소스파일의 일부인 셈이다. 그래서 두번 이상 중복정의되는 경우가 쉽게 발생할 수 있다. 그럼 어떻게 해야 중복을 피할수있을까? 1) hdr1.h, hdr2.h 의 내용을 모두 main.cpp 에 옴긴다 2) hdr1.h 의 내용을 hdr2.h 로 옮기고 main.cpp 에서는 hdr2.h 만 include 한다. 3) 다른 건 다 그대로 놔두고 tips1.cpp 에서 hdr1.h 은 include 하지 않는다. 작은프로그램이고 포함관계가 적다면 이렇게해도 해결될것이다. 하지만 그게 아니라 프로그램이 거대하고 포함관계가 복잡하다면 .. 그래도 이렇게 하는게 좋을까? 파일을 나누는 이유를생각해보자. 과연 이게 현명한 선택인지.. 그럼 어떻게해야할까? 답은 좀 더 근본적인 방법은 모든 헤더 파일을 다음과 같이 작성하는 것이다 // 헤더 파일의 제일 첫 부분 01: #ifndef HDR_H // 헤더 파일명을 대문자한 매크로가 정의되어 있지 않으면 02: #define HDR_H // 헤더 파일명 매크로를 정의한다 ...... // 헤더 파일 본 내용이 여기 들어갑니다 03: #endif // ifndef HDR_H 에 매치됩니다 그럼 이방법을 이용해 해결해보자 hdr1.h 파일
#ifndef HDR1_H #define HDR1_H class DummyBase { private: int _i; public: DummyBase(int i): _i(i) { } int Get() { return _i; } void Set(int i) { _i = i; } }; #endif hdr2.h main.cpp 은 같으므로 생략하도록하자. define.h 파일 #ifndef DEFINE_H // 중복인클루드 방지 #define DEFINE_H // 중복인클루드 방지 #include "main.h" // DEFINE_BUS #define DEFINE_CAR #undef DEFINE_PLANE #ifdef DEFINE_BUS #define CAR_TYPE "Bus" #define CAR_NUMBER 10 #else #define CAR_TYPE "Taxi" #defien CAR_NUMBER 2 #endif #endif // DEFINE_H // 중복인클루드 방지 자동차에 대한 정의파일이다. 버스에 대한 기능으로 동작하게 컴파일하고 싶으면, DEFINE_BUS을 define하면 되고, 그렇지 않으면 택시에 대한 기능으로 동작하게 컴파일이 된다.
datatype.h #ifndef DATATYPE_H
#define DATATYPE_H
#include "define.h"
typedef struct
{
int number[ CAR_NUMBER ];
} DATA;
#endif // DATATYPE_H
main.h 파일 #ifndef MAIN_H // 중복인클루드 방지 #define MAIN_H // 중복인클루드 방지 #include "datatype.h" // main.c에서 DATA 사용하기 위해 #ifdef DEFINE_CAR #define DEFINE_BUS #define DEFINE_TAXI #else #define DEFINE_ROKET #define DEFINE_AIRPLANE #endif #endif // MAIN_H // 중복인클루드 방지 메인 프로그램을 위한 헤더파일로 프로그램의 전체적인 설정내용이 들어 있다. 어떤 것이 정의되었고 정의되지 않았느냐에 따라서 프로그램 자체가 바뀌어버릴 수 있다. main.c 파일 #include "main.h" void main(void) { int i; DATA data; for( i=0; i < CAR_NUMBER; i++ ) data.number[i] = i; printf("%s", CAR_TYPE); } 메인 프로그램이다. 여기서 CAR_TYPE을 출력하게 된다. 무엇이 출력될까? 그리고 CAR_NUMBER는 무슨 값일까...? 위의 예제는 헤더파일이 꼬인 문제를 예제로 만들어보기 위해서 억지로 꾸민 것이긴 한데, 이런 경우 컴파일이 되지 않거나 원하지 않는 결과를 낳게 된다. main.c #ifdef DEFINE_CAR 해결방법은......? 가급적 헤더파일들은 헤더파일들끼리 연결시키지 말고, 가급적 소스상에서만 인클루드 하길 권한다. 차라리 에러라도 나면 다행이지만, 원하지 않는 결과가 나왔을 경우에는 수천개의 파일을 뒤져보더라도 원인을 못찾을 수 있다. 위의 소스에서 출력결과가 "Bus"가 아니라, "Taxi"가 나오는 경우처럼 말이다. 수십 수백개의 파일을 어떻게 다 하라고 하지만 모든 헤더파일을 모으는 것이 가장 최선이라고는 할 수 없다. 아주 공통적인 헤더파일들만 모으고, 그 이외에는 소스에서 직접 인클루드 해주면 된다. 항상 생각을 하고 살자 |
|
Tag // include
댓글을 달아 주세요