Item*)로 “Weapon/Armor를 한 타입으로 다루는” 이유Item* 하나로 무기/방어구를 다룰 수 있는 이유를 설명할 수 있다. ┌──────────┐
│ Item │ _itemId, _itemCount, _rarity, _itemType
└────┬─────┘
│
┌──────┴──────┐
│ │
┌─────▼─────┐ ┌────▼─────┐
│ Weapon │ │ Armor │
│ _damage │ │ _defence │
└───────────┘ └──────────┘
Item을 Item*로 들고 있다가 나중에 삭제하는 구조라면,
부모 소멸자는 반드시 virtual이어야 합니다.
class Item {
public:
virtual ~Item() = default; // 필수 규칙
};
이 규칙이 없으면:
Item* p = new Weapon(); delete p; 같은 코드에서#include <cstdlib>
Item* DropItemRaw()
{
if (std::rand() % 2 == 0)
return new Weapon();
else
return new Armor();
}
// 사용 예(핵심: 반드시 delete)
Item* item = DropItemRaw();
// ... 사용 ...
delete item;
item = nullptr;
이 방식은 배우기엔 좋지만, 실전에서는 “delete 누락”이 너무 쉽게 발생합니다.
std::unique_ptr<Item>로 소유권을 타입에 담기#include <cstdlib>
#include <memory>
std::unique_ptr<Item> DropItem()
{
if (std::rand() % 2 == 0)
return std::make_unique<Weapon>();
else
return std::make_unique<Armor>();
}
// unique_ptr은 범위를 벗어나면 자동으로 delete(누수 방지)
이후 Step에서 스마트 포인터를 배우면, Drop 함수는 거의 항상 이런 형태로 귀결됩니다.
enum ItemRarity { IR_None, IR_Normal, IR_Rare, IR_Unique };
enum ItemType { IT_None, IT_Weapon, IT_Armor };
class Item {
public:
explicit Item(ItemType type) : _itemType(type) {}
virtual ~Item() = default;
virtual void PrintInfo() {}
ItemType GetItemType() const { return _itemType; }
protected:
int _itemId = 0;
int _itemCount = 0;
ItemRarity _rarity = IR_None;
ItemType _itemType = IT_None;
};
포인트:
Item* 하나로 Weapon/Armor를 담아둘 수 있는 이유는?virtual ~Item()이 필수일까?