포스트

[C++] #include

[C++] #include

C++에서 #include란?


1. #include란 무엇인가?

  • 전처리기 지시문 중 하나로, 다른 파일의 내용을 현재 파일로 텍스트 복사
  • 주로 헤더 파일(.h) 을 포함하여 함수, 클래스, 상수 선언을 가져오기 위해 사용
1
2
#include <iostream>   // 표준 라이브러리
#include "MyHeader.h" // 사용자 정의 헤더

2. 동작 원리

  • 컴파일 과정 중 전처리 단계에서 작동
  • #include된 파일의 내용이 텍스트로 그대로 삽입

전처리 후 예시

1
2
3
4
5
6
7
8
9
10
// main.cpp
#include "math_utils.h"
int main() {
    return square(3);
}

// math_utils.h
int square(int x) {
    return x * x;
}

전처리 결과:

1
2
3
4
5
6
int square(int x) {
    return x * x;
}
int main() {
    return square(3);
}

3. include 형식

형식의미예시
#include <...>시스템 헤더, 표준 라이브러리<vector>
#include "..."사용자 정의 헤더"MyHeader.h"

4. 주요 목적

  • 코드 재사용 (함수, 클래스 재사용)
  • 선언/정의 분리
  • 표준 라이브러리 기능 활용


C++에서 #include를 어디에 쓰는 것이 좋을까?


1. 기본 원칙 요약

include 대상추천 위치
클래스, 함수 선언에 필요한 헤더.h 파일
구현에만 필요한 헤더 (지역적 사용).cpp 파일

2. 헤더(.h)에 include 해야 할 경우

클래스 정의나 함수 시그니처에 직접 사용되는 타입이라면 헤더에 #include 해야 합니다.

1
2
3
4
5
6
7
// MyClass.h
#include <string>  // std::string을 멤버 변수로 사용

class MyClass {
public:
    std::string name;
};
  • 이렇게 하면 이 헤더를 포함하는 .cpp 파일에서도 문제가 없이 사용할 수 있습니다.

3. 소스 파일(.cpp)에 include 해야 할 경우

구현에만 필요한 경우 .cpp에 include 하세요.

1
2
3
4
5
6
7
// MyClass.cpp
#include "MyClass.h"
#include <iostream>  // 구현에만 필요

void MyClass::Print() {
    std::cout << name << std::endl;
}
  • 불필요한 의존성을 .h에 포함시키지 않아도 됩니다.

4. 헤더에 너무 많은 include를 넣으면 생기는 문제점

1. 컴파일 시간 증가

  • 헤더 파일이 include되면 해당 내용이 텍스트로 복사되어 들어가므로,
  • 많이 include된 헤더는 매번 재처리되어 빌드 속도가 느려집니다.
1
2
3
4
5
6
7
// A.h
#include <vector>
#include <map>
#include <algorithm>

// B.cpp
#include "A.h"
  • A.h를 포함하면 <vector>, <map>, <algorithm>까지 컴파일해야 하므로 시간이 늘어납니다.

2. 순환 참조(circular include)

  • 두 개의 헤더가 서로를 include하면 무한 루프가 발생합니다.
1
2
3
4
5
6
7
8
9
10
11
// A.h
#include "B.h"
class A {
    B* b;
};

// B.h
#include "A.h"
class B {
    A* a;
};

#include 가드나 #pragma once로 방지할 수 있지만, 전방 선언(forward declaration) 을 사용하는 것이 더 좋습니다.


3. 의존성 확산

  • A 헤더가 B를 include하고, C가 A를 include하면 C도 B에 의존하게 됩니다.
  • → 유지보수 어려움 증가, 의존 관계 복잡해짐
1
2
3
4
5
6
7
8
9
// A.h
#include "HeavyLibrary.h"

class A {
    HeavyType t;
};

// C.cpp
#include "A.h"  // 여기서도 HeavyLibrary까지 따라 들어옴

HeavyLibrary는 C에 필요 없지만 의존하게 되어버림


5. 전방 선언(forward declaration)을 고려하자

1
2
3
4
5
6
7
8
9
10
11
12
// Bad.h
#include "BigClass.h"

class Bad {
    BigClass b;
};

// Good.h
class BigClass;  // 전방 선언
class Good {
    BigClass* b;  // 포인터만 사용할 때 가능
};
  • 전방 선언을 사용하면 .h에서 include 하지 않아도 되고, .cpp에서만 include 하면 됩니다.

6. 결론

상황include 위치
함수 인자, 멤버 변수로 사용.h
구현 내부에서만 사용.cpp
포인터/참조만 쓸 경우.h에서 전방 선언 후 .cpp에 include
빌드 시간 최적화 원할 때필요 최소한만 .h에 포함
  • include는 꼭 필요한 곳에만, 가급적 .cpp에
  • 전방 선언을 적극 활용
  • 헤더는 작고 독립적으로 유지하는 것이 좋음
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.