기본 패턴
cpp
// user.h
#pragma once
#include <string>
class User {
public:
explicit User(std::string name);
void print() const;
private:
std::string name;
};설명
- C++ 프로젝트는 보통 "외부에 보여 줄 선언"과 "실제 구현"을 분리해 관리합니다.
- 헤더 파일에는 클래스 선언, 함수 선언, 타입 정의처럼 다른 파일이 알아야 하는 인터페이스를 두고,
.cpp파일에는 실제 구현을 둡니다. - 이 구조를 지키면 의존 관계를 더 명확하게 관리할 수 있고, 수정이 생겼을 때 무엇이 다시 컴파일되어야 하는지도 이해하기 쉬워집니다.
- 클래스 멤버 함수 정의를
User::print()처럼 네임스페이스/클래스 소속과 함께 쓰는 이유도 이 분리 구조 안에서 자연스럽게 드러납니다. - 헤더는 포함되는 횟수가 많기 때문에 불필요한 의존성을 줄이고, include guard나
#pragma once로 중복 포함을 막는 습관이 중요합니다.
짧은 예제
cpp
// user.cpp
#include "user.h"
#include <iostream>
#include <utility>
User::User(std::string name) : name(std::move(name)) {}
void User::print() const {
std::cout << name << "\n";
}빠른 정리
| 항목 | 설명 |
|---|---|
| 헤더 파일 | 선언과 인터페이스를 담음 |
| 소스 파일 | 실제 함수와 메서드 구현을 담음 |
#pragma once | 헤더 중복 포함을 막는 간단한 방법 |
Class::method | 클래스에 속한 구현임을 명시 |
| 장점 | 의존성 관리와 분할 컴파일에 유리 |
주의할 점
헤더에 구현을 무분별하게 넣으면 포함하는 파일 수만큼 컴파일 비용이 커지고, 중복 정의 문제도 생길 수 있습니다. 무엇이 인터페이스이고 무엇이 구현인지 먼저 나누는 편이 좋습니다.