Item* 배열로 설계할 때의 핵심 계약(소유권/삭제 책임)AddItem/RemoveItem API에서 “누가 delete 책임인지”를 명확히 설계할 수 있다.class Item;만으로 가능한 것/불가능한 것을 구분할 수 있다.Item* _items[MAX_SLOT]는 “아이템 객체를 직접 저장”하는 게 아니라,
힙에 있는 아이템을 가리키는 주소만 저장합니다.
Inventory::_items
[0] -> Weapon 객체(힙)
[1] -> Armor 객체(힙)
[2] -> nullptr
...
따라서 핵심은 하나입니다.
권장 계약 예시(학습용 raw pointer 기준):
bool AddItem(Item* item)Item* RemoveItem(int slot)class Inventory {
public:
static constexpr int MAX_SLOT = 20;
bool AddItem(Item* item); // 성공 시 소유권 획득
Item* RemoveItem(int slot); // 소유권 반환(호출자에게 이동)
Item* GetItemAtSlot(int slot) const;
private:
Item* _items[MAX_SLOT] = {};
};
실전에서는
std::unique_ptr<Item>로 소유권을 타입에 담는 방식이 더 안전합니다.
헤더에서 Item을 “포인터/참조”로만 다루면 정의가 없어도 됩니다.
// Inventory.h
#pragma once
class Item; // 전방 선언
class Inventory {
private:
Item* _items[20] = {};
};
그리고 실제 구현이 필요한 cpp에서만 include 합니다.
// Inventory.cpp
#include "Inventory.h"
#include "Item.h" // 여기서 실제 정의 필요
Item*, Item&, 함수 선언의 인자/반환 타입Item 객체를 값으로 멤버 보관, sizeof(Item), 멤버 접근(item->PrintInfo() 등)문제 패턴:
Item.h가 #include "Inventory.h"Inventory.h가 #include "Item.h"해결 패턴:
헤더(.h):
필요한 타입이 포인터/참조면 -> 전방 선언만
소스(.cpp):
실제 구현이 필요한 곳에서만 include
이렇게 하면:
AddItem이 실패했을 때 누가 delete해야 하는가?Item 객체를 값으로 멤버에 둘 수 없는 이유는?