중복 정의 문제
식별자는 하나의 정의만 가질 수 있다. 따라서 변수 식별자를 두 번 이상 정의한 프로그램은 오류가 발생한다.
int main()
{
int x; // 식별자 x에 대한 정의
int x; // compile error: duplicate definition
return 0;
}
함수를 두 번 이상 정의하는 프로그램도 컴파일 오류가 발생한다.
#include <iostream>
int foo()
{
return 5;
}
int foo() // compile error: duplicate definition
{
return 5;
}
int main()
{
std::cout << foo();
return 0;
}
이러한 프로그램은 헤더 파일을 이용해서 쉽게 수정할 수 있지만, 헤더 파일이 두 번 이상 포함될 경우 문제가 발생할 수 있다.
math.h:
int getSquareSides()
{
return 4;
}
geometry.h:
#include "math.h"
main.cpp:
#include "math.h"
#include "geometry.h"
int main()
{
return 0;
}
위 프로그램은 컴파일되지 않는다. main.cpp에서는 getSquareSides() 함수에 대한 정의가 있는 math.h를 복사한다. 또한 main.cpp는 math.h를 포함한 geometry.h를 복사한다.
모든 #include
지시자를 해결한 main.cpp는 다음과 같다.
int getSquareSides() // from math.h
{
return 4;
}
int getSquareSides() // from geometry.h
{
return 4;
}
int main()
{
return 0;
}
결국에 main.cpp는 중복된 함수 정의로 인해 컴파일 오류가 발생한다.
헤더 가드(header guard)라는 메커니즘을 통해 위 문제를 해결할 수 있다. 헤더 가드는 조건부 컴파일 지시자를 사용한다.
#ifndef SOME_UNIQUE_NAME_HERE
#define SOME_UNIQUE_NAME_HERE
// 선언과 정의
#endif
위 헤더 파일이 포함(include)되면 SOME_UNIQUE_NAME_HERE
가 정의되었는지 확인한다. 헤더 파일을 처음 include하면 SOME_UNIQUE_NAME_HERE
는 정의되어 있지 않다. 그러므로 SOME_UNIQUE_NAME_HERE
를 정의하고 헤더 파일의 내용을 include한다. 그러나 이전에 헤더 파일을 include 했다면 SOME_UNIQUE_NAME_HERE
는 이미 정의되어 있기 때문에 헤더 파일 내용이 무시된다.
모든 헤더 파일에는 헤더 가드가 있어야 한다. SOME_UNIQUE_NAME_HERE
은 일반적으로 _H
가 붙은 헤더 파일의 이름을 사용한다.
math.h:
#ifndef MATH_H
#define MATH_H
int getSquareSides()
{
return 4;
}
#endif
#pragma once
현재 많은 최신 컴파일러는 #pragma
지시자를 이용한 단순한 헤더 가드를 지원한다.
#pragma once
// your code here
#pragma once
는 헤더 가드와 같은 기능을 하며, 짧다는 게 장점이다.
그러나 C++ 언어의 공식적인 부분이 아니므로 모든 컴파일러가 지원하는 것은 아니다. 호환성을 위해 헤더 가드를 사용하는 것이 좋다.
번역: 이 포스트의 원문은 http://www.learncpp.com/cpp-tutorial/1-10a-header-guards/ 입니다.