포스트

TIL 2026-03-17

TIL 2026-03-17

2026.03.17 | C++ 과제 1~3 정리

📗 과제 1 — 상태창 구현 (C++ 기초)

핵심 개념

개념내용
배열int stat[4]stat[0]=HP, stat[1]=MP, stat[2]=공격력, stat[3]=방어력
포인터 매개변수void setPotion(int count, int* p_HPPotion, int* p_MPPotion)
while + switch0번 입력 전까지 메뉴 반복 출력
입력 유효성 검사HP·MP > 50, 공격력·방어력 > 0 강제

핵심 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 포인터로 값 직접 수정
void setPotion(int count, int* p_HPPotion, int* p_MPPotion) {
    *p_HPPotion = count;
    *p_MPPotion = count;
}

// 무한루프 메뉴
while (1) {
    cin >> choice;
    if (choice == 0) break;
    switch (choice) {
        case 1:
            if (HPPotion <= 0) { cout << "포션이 부족합니다." << endl; continue; }
            stat[0] += 20;
            HPPotion--;
            break;
    }
}

배운 점

  • * 역참조로 포인터가 가리키는 값을 직접 변경하는 방식 이해
  • const int SIZE = 4;const 키워드로 상수 선언
  • 포션이 0개일 때 continue로 루프 재시작하는 흐름 제어

📗 과제 2 — 전직 시스템 & 전투 시스템 (OOP)

핵심 개념

개념설명
추상 클래스virtual void attack() = 0 → 순수 가상 함수로 자식 구현 강제
상속class Warrior : public Player
다형성Player* player = new Warrior(nick) → 부모 포인터로 자식 동작
가상 소멸자virtual ~Player() → 자식 객체 안전 소멸
오버로딩attack() / attack(Monster*) 두 버전 공존

파일 구조

1
2
3
4
5
6
7
assignment-2/
├── player.h / player.cpp       # 추상 기반 클래스
├── warrior.h / warrior.cpp     # 전사 (HP 150, 검 공격)
├── magician.h / magician.cpp   # 마법사 (MP 150, 마법 화살)
├── thief.h / thief.cpp         # 도적 (5회 연속 공격)
├── archer.h / archer.cpp       # 궁수 (3회 연속 공격)
└── monster.h / monster.cpp     # 몬스터 (HP 10, 공격력 30)

핵심 코드

1
2
3
4
5
6
7
8
9
10
11
12
// 다형성 활용
Player* player = nullptr;
switch (job_choice) {
    case 1: player = new Warrior(nickname);  break;
    case 2: player = new Magician(nickname); break;
    case 3: player = new Thief(nickname);    break;
    case 4: player = new Archer(nickname);   break;
}
player->attack();           // 직업에 맞는 attack() 자동 호출
player->attack(monster);    // 오버로딩된 버전 호출

if (player != nullptr) delete player;  // 메모리 해제

배운 점

  • 순수 가상 함수 : = 0 으로 자식이 반드시 구현하도록 강제 — 추상 클래스로 만듦
  • 전방 선언(Forward Declaration) : class Monster; 헤더에서 순환 참조 방지
  • LNK2019 오류 : cl.exe 빌드 시 .cpp 파일을 하나만 넣으면 다른 심볼을 찾지 못함 → 모든 .cpp를 함께 전달해야 함

📗 과제 3 — 인벤토리 시스템 (템플릿 & 메모리 관리)

핵심 개념

개념설명
템플릿template <typename T> — 타입에 무관한 범용 클래스
동적 배열T* pItems_ = new T[capacity_]
깊은 복사복사 생성자에서 new T[]로 새 메모리 할당 후 데이터 복사
자동 확장(Resize)꽉 차면 capacity_ * 2 크기로 재할당
std::sortsort(pItems_, pItems_ + size_, compareItemsByPrice)

핵심 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template <typename T>
class Inventory {
public:
    Inventory(int capacity = 5);              // Default Argument
    Inventory(const Inventory<T>& other);     // 복사 생성자 (깊은 복사)
    ~Inventory() { delete[] pItems_; pItems_ = nullptr; }

    bool AddItem(const T& item);   // 꽉 차면 Resize() 자동 호출
    bool RemoveLastItem();         // size_-- 만으로 논리적 제거
    void SortItems();              // std::sort 활용
    Inventory<T>& Assign(const Inventory<T>& other);  // 대입 깊은 복사

private:
    void Resize(int newCapacity);
    T*  pItems_;
    int capacity_, size_;
};

Resize 내부 동작 흐름

1
2
3
4
5
1. new T[newCapacity]   →  새 메모리 할당
2. 기존 데이터 복사      →  for (i < size_) newItems[i] = pItems_[i]
3. delete[] pItems_     →  기존 메모리 해제
4. pItems_ = newItems   →  포인터 교체
5. capacity_ 갱신

배운 점

  • 얕은 복사 vs 깊은 복사 : 기본 복사는 포인터 주소만 복사 → 소멸 시 double free 발생. new로 새 공간을 만들어야 안전
  • Default Argument : 생성자를 여러 개 만들지 않고 Inventory(int capacity = 5) 하나로 통합
  • std::vector의 원리 : 이번 Inventory<T>가 바로 vector의 핵심 동작 방식 (push_back, resize, 깊은 복사)
  • Unreal의 TArray도 같은 원리로 동작

오늘 해결한 트러블슈팅

문제원인해결
한글 깨짐 (?꾩궗)파일이 EUC-KR 인코딩, VS가 BOM 없이 CP949로 읽음UTF-8 BOM 추가 + /utf-8 컴파일 플래그
LNK2019 링커 오류cl.exeMain.cpp만 전달모든 .cpp 파일을 함께 컴파일
솔루션 용량 과다.vs/, Debug/, .obj 등 빌드 산출물 추적됨.gitignore에 패턴 기반 규칙 추가, 캐시 삭제

언리얼 엔진과의 연결고리

  • 과제 1 → 게임 오브젝트 상태 관리의 기초 (HP바, 버프 시스템)
  • 과제 2AActor / APawn 상속 구조, UFUNCTION 오버라이딩
  • 과제 3TArray<T> 내부 원리 이해, 메모리 관리 역량

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.