코딩

[C++] 인벤토리 시스템 구현— Project HW03

story98138 2026. 3. 17. 17:41

1. 오늘의 개발 개요

게임 내에서 아이템, 무기, 포션 등 다양한 데이터를 담을 수 있는 범용적인 데이터 보관함(Inventory)을 설계하고 구현했습니다. 데이터를 정의하는 Item 클래스를 먼저 설계하고, C++의 템플릿(Template)동적 메모리 할당을 활용해 어떤 데이터든 담을 수 있고 스스로 크기가 늘어나는 인벤토리를 완성했습니다.

 

Item 기초 설계
Inventory 템플릿 구현
메모리 확장(Resize) 구현
Main 구동 및 테스트

2. 프로젝트 환경 설정

개발 환경 Visual Studio 2022
솔루션 HW03.sln
소스 파일 Item.h, Item.cpp, Inventory.h, main.cpp (총 4개 파일)

3. 핵심 구현 1: Item 클래스 (데이터 객체)

인벤토리에 담길 알맹이인 Item 클래스입니다. 데이터(이름, 가격)는 private으로 은닉하고, 정보를 읽거나 비우는(Clear) 기능만 외부에 열어두어 캡슐화를 지켰습니다. 특히 std::sort를 위해 클래스 외부에 가격 비교 함수를 분리하여 선언한 것이 특징입니다.

// Item.h 및 Item.cpp 주요 로직
class Item {
public:
    Item() : name_(""), price_(0) {} // 동적 배열 생성을 위한 기본 생성자 필수
    Item(const std::string& name, int price);

    void Clear() { // 아이템 제거 시 데이터를 안전하게 비움
        name_ = "";
        price_ = 0;
    }
    void PrintInfo() const;
    int GetPrice() const { return price_; }

private:
    std::string name_;
    int price_;
};

// 정렬에 사용할 비교 함수 (클래스 외부 선언)
bool compareItemsByPrice(const Item& a, const Item& b) {
    return a.GetPrice() < b.GetPrice(); // 가격 오름차순 반환
}

4. 핵심 구현 2: Inventory 템플릿과 자동 확장

어떤 데이터든 담을 수 있는 템플릿 클래스 Inventory<T>입니다. 가방이 꽉 찼을 때 메모리를 2배로 재할당하여 데이터를 이주시키는 딥 카피(Deep Copy)메모리 누수 방지(delete[])에 신경 썼습니다.

// Inventory.h 주요 로직
template<typename T>
class Inventory {
private:
    T* pItems_;     // 동적 배열 포인터
    int capacity_;  // 최대 용량
    int size_;      // 현재 담긴 개수

public:
    // 메모리 자동 확장 로직 (언리얼 TArray의 핵심 원리)
    void Resize(int newCapacity) {
        T* pNewItems = new T[newCapacity];         // 1. 새 공간 할당
        for (int i = 0; i < size_; ++i) {
            pNewItems[i] = pItems_[i];             // 2. 기존 데이터 복사 (이사)
        }
        delete[] pItems_;                          // 3. 기존 메모리 해제 (누수 방지!)
        pItems_ = pNewItems;                       // 4. 새 주소 갱신
        capacity_ = newCapacity;
    }

    void AddItem(const T& item) {
        if (size_ >= capacity_) Resize(capacity_ * 2); // 꽉 차면 2배 확장
        pItems_[size_++] = item;
    }
};

5. 메인 로직 구동 및 실행 결과

설계한 클래스들을 main.cpp에서 조립했습니다. 초기 용량을 2로 설정한 Inventory에 아이템 3개를 밀어 넣어 자동 확장이 정상 작동하는지 테스트하고, SortItems()로 가격 정렬을 수행했습니다.

// main.cpp
#include <iostream>
#include "Item.h"
#include "Inventory.h"

int main() {
    // 용량이 2칸인 아이템 인벤토리 생성
    Inventory<Item> myInven(2);

    // 3개를 넣음으로써 내부적으로 Resize가 발생함!
    myInven.AddItem(Item("빨간 포션", 50));
    myInven.AddItem(Item("강철 검", 300));
    myInven.AddItem(Item("나무 방패", 100));

    std::cout << "--- 정렬 전 ---" << std::endl;
    myInven.PrintAllItems();
    
    myInven.SortItems(); // 가격 기준 오름차순 정렬

    std::cout << "\n--- 정렬 후 ---" << std::endl;
    myInven.PrintAllItems();

    return 0;
}
--- 정렬 전 ---
[이름: 빨간 포션 | 가격: 50G]
[이름: 강철 검 | 가격: 300G]
[이름: 나무 방패 | 가격: 100G]

--- 정렬 후 ---
[이름: 빨간 포션 | 가격: 50G]
[이름: 나무 방패 | 가격: 100G]
[이름: 강철 검 | 가격: 300G]