서버를 만들기 전에...
기본적인 클라이언트를 구성하고 그 위에 얹어보려고 한다
이미 플레이어가 움직이고 인벤토리가 추가되게 하는 로직을 imgui로 띄우는 것까지 해두었는데, 정리가 필요해서 코드 짠 것도 수정하고 끄적여 보는 시간을 가져야 겠다
#include <vector>
class Inventory
{
public:
Inventory(int cap = 10) :capacity(cap) {}
//~Inventory()
//{
// for (Item* item : items)
// {
// delete item;
// }
//}
// bool addItem(Item* newItem);
bool addItem(std::unique_ptr<Item> newItem);
void showList();
void useItem();
int getSize() const { return items.size(); } // 현재 들어있는 아이템 개수
int getCapacity() const { return capacity; } // 최대 칸 수 (10)
private:
//std::vector<Item*> items;
std::vector<std::unique_ptr<Item>> items;
int capacity;
};
나는 스마트 포인터의 장점과 사용법을 몰랐기 때문에 그냥 아는 대로만 구현을 했었다
근데 관련해서 공부를 하다보니 스마트 포인터를 쓰면 그냥 포인터를 섰을 때 혹시 모를 메모리 누수를 방지할 수 있어 적극적으로 쓰는 것을 권장한다는 말을 듣고 코드를 수정하기로 했다.
우선
std::vector<Item*> items;
로 추상 클래스(부모 클래스인) Item 벡터를 포인터로 담아 여러 가지 아이템(자식 클래스들)을 담게 하였다
그리고 main.cpp에서
if (ImGui::Button("장검 추가")) {
//인자를 new Weapon("Sword",10)에서 수정
if (myInven.addItem(std::make_unique<Weapon>("Sword", 10))) {
std::cout << "장검을 가방에 넣었습니다." << std::endl;
}
else {
std::cout << "가방이 가득 찼습니다!" << std::endl;
}
}
근데 여기서 왜 포인터로 담았냐하면
우선 Item은 추상 클래스이기 때문에 자식 클래스에서 구현을 해줘야만 해서
class Item
{
std::string name;
}
class Weapon : public Item
{
std::string name; // 부모(Item)에게 물려받음
int damage; // Weapon이 가진 고유 특성
}
요런 식으로 구현이 되는데
메모리를 박스로 표현하면:
Item 박스:
┌──────────┐
│ name │
└──────────┘
Weapon 박스:
┌──────────┬──────────┐
│ name │ damage │
└──────────┴──────────┘
따라서 vector으로 vector에 담게 되면 Item 타입만 담게 돼서 damage 정보는 버려지는 객체 슬라이싱 이슈가 발생하기 때문이다
근데 포인터를 넣게 되면 객체 원본이 아니라 주소값을 저장하니까 해당 타입이 갖고 있는 정보를 다 가져올 수 있게 된다