static의 2가지 의미static 멤버 변수/함수static 변수(호출 사이 값 유지)static 멤버 변수의 정의(ODR) 규칙과 자주 나는 링크 에러 원인static 멤버 변수에서 unresolved external symbol이 나는 이유를 설명할 수 있다.static이 왜 “한 번만 초기화되고 값이 유지”되는지 설명할 수 있다.m1.hp, m2.hp는 서로 다른 저장공간)Marine::attack은 모두가 공유)┌─────────────────────────────────────────────────────────────────────────────┐
│ Marine m1, m2, m3; (hp=일반, attack=static) │
├─────────────────────────────────────────────────────────────────────────────┤
│ [일반 멤버 hp] [static 멤버 attack] │
│ 객체마다 따로 클래스 전체에서 1개 │
│ │
│ m1.hp m2.hp m3.hp Marine::attack (공유) │
│ │
│ static 함수는 객체 없이도 호출 가능: Marine::SetAttack(7) │
│ 단, static 함수 안에서는 일반 멤버(hp)에 접근 불가(= this가 없음) │
└─────────────────────────────────────────────────────────────────────────────┘
class Marine {
public:
int hp = 40; // 객체마다 다름
static int attack; // 모두가 공유
};
int Marine::attack = 6; // (중요) 클래스 밖에서 '정의' + 초기화
static int Marine::attack;는 “선언”이고,unresolved external symbol "public: static int Marine::attack" ...inline static으로 헤더에서 끝내기헤더만으로 끝내고 싶다면(학습용 감각):
class Marine {
public:
inline static int attack = 6; // C++17부터 가능(ODR 문제 완화)
};
class Marine {
public:
static void SetAttack(int value)
{
attack = value; // OK (static 멤버)
// hp = 10; // ERROR (일반 멤버, this가 없음)
}
int hp = 40;
inline static int attack = 6; // 예시용(C++17)
};
정리:
Marine::SetAttack(7);class Player {
public:
Player() : id(s_idGenerator++)
{
}
int id = 0;
inline static int s_idGenerator = 1; // C++17 예시(아니면 cpp에 정의)
};
포인트:
#include <iostream>
void CountCalls()
{
static int counter = 0; // 최초 1회만 초기화
++counter;
std::cout << "함수가 " << counter << "번 호출되었습니다.\n";
}
핵심:
싱글톤은 “딱 하나만 존재하고 어디서든 접근”이 필요할 때 쓰지만,
전역 상태이기 때문에 남용하면 테스트/의존성/순서 문제가 커집니다.
class UserManager {
public:
static UserManager& Instance()
{
static UserManager instance; // 프로그램 전체에서 1개
return instance;
}
void AddUser() { ++_userCount; }
int GetUserCount() const { return _userCount; }
UserManager(const UserManager&) = delete;
UserManager& operator=(const UserManager&) = delete;
private:
UserManager() = default;
int _userCount = 0;
};
사용 예:
auto& mgr = UserManager::Instance();
mgr.AddUser();
mgr.GetUserCount();
Instance())나 지역 참조(auto& mgr = ...)로 충분히 깔끔하게 쓸 수 있습니다.static 멤버 변수에서 링크 에러가 나는 가장 흔한 원인은?