extern / 전방 선언 / 헤더 가드로 발생하는 문제를 예방하는 방법#include가 “붙여넣기”에 가깝다는 것을 설명할 수 있다.| 이유 | 설명 |
|---|---|
| 가독성·유지보수 | 한 파일에 모든 코드 → 관리 어려움 |
| 협업 | 파일별로 분리 → Git 등에서 충돌 감소 |
| 컴파일 시간 | 변경된 파일만 재컴파일 → 빌드 속도 개선 |
| 모듈화 | 기능별 분리 → 확장·객체지향 설계 용이 |
| 구분 | 선언 (Declaration) | 정의 (Definition) |
|---|---|---|
| 역할 | "이게 있다"고 알림 | 실제 구현 |
| 위치 | .h (헤더) | .cpp (소스) |
| 메모리 | 사용 안 함 | 사용함 |
핵심 감각:
소스(.cpp) → [전처리] → [컴파일] → [어셈블] → 목적파일(.obj)
↓
[링킹] → 실행파일(.exe)
.cpp는 독립적으로 컴파일됩니다. (컴파일 단위 = Translation Unit)#include는 전처리 단계에서 해당 파일 내용을 그 자리로 복사/붙여넣기 합니다..obj를 모아, “선언만 있고 아직 비어있는 호출”을 실제 정의에 연결합니다.전처리 관점으로 보면:
// GameCoding.cpp
#include "Helper.h"
int main() { Test2(); }
↓ (전처리 후, 개념적으로)
// GameCoding.cpp
// --- Helper.h 내용이 여기에 그대로 들어옴 ---
void Test2();
// ------------------------------------------
int main() { Test2(); }
#include "Helper.h" → Helper.h 내용을 그 위치에 복사.#include <iostream> → 표준 라이브러리 헤더 포함.#ifndef HELPER_H
#define HELPER_H
// ... 내용 ...
#endif__(더블 언더스코어)는 구현 예약 영역인 경우가 많아 피하는 게 안전합니다..cpp가 그 내용을 함께 “붙여넣기”로 가져가기 때문입니다.using namespace std; (전역 오염)<iostream> 같은 무거운 include실전 규칙(암기):
전역 변수도 함수와 같은 문제가 생깁니다.
int GTest;를 써버리면, 그 헤더를 include하는 모든 .cpp에 정의가 복사되어그래서 전역 변수는 다음 규칙을 씁니다.
extern int GTest; → “다른 곳에 정의가 있다”int GTest = 0; → 실제 메모리 할당#pragma once
void Test(int value);
void Test2();
extern int GTest;
extern int GTest: GTest는 정의되지 않았으며, 다른 파일에서 정의될 것임을 의미.#include "Helper.h"
#include <iostream>
using namespace std;
int GTest = 0; // 실제 메모리 공간 할당(정의는 여기 1번만)
void Test(int value) {
(void)value;
Test2();
}
void Test2() {
cout << "Hello World" << '\n';
}
#include "Helper.h"
int main() {
GTest = 100;
Test2();
return 0;
}
#include "Helper.h"로 선언을 포함하고, 정의는 Helper.cpp에 있으므로 링커가 연결합니다.class MyClass; // 전방 선언
void doSomething(MyClass* obj); // 정의 없이 포인터 사용 가능
MyClass의 내부 멤버를 접근하거나 크기를 알아야 하면(값으로 들고 있으면) 정의가 필요합니다.#include "MyClass.h"를 추가합니다.| 에러 | 원인 |
|---|---|
선언되지 않음 | #include 누락, 또는 선언 누락 |
LNK: 확인할 수 없는 외부 기호 | 선언만 있고 정의(구현) 없음 |
LNK: 중복 정의 | 헤더에 정의를 넣었거나 전역/함수를 여러 cpp에서 정의 |
| 시그니처 불일치 | 선언과 정의의 매개변수·리턴 타입/네임스페이스가 다름 |
extern 규칙(선언은 헤더, 정의는 cpp 1개)을 지켰는지#include는 “참조”인가 “붙여넣기”인가?extern이 필요한가?