세 번째 실습 과제를 풀어보았습니다!
Inventory<T> 클래스 구현
Item 뿐만 아니라, Weapon, Potion 등 어떤 타입의 객체든 저장할 수 있도록 템플릿 클래스로 작성합니다.
- 클래스 이름:
Inventory - 템플릿:
template <typename T>를 사용하여 어떤 타입(T)의 데이터든 처리할 수 있도록 합니다.
멤버 변수 (private)
T* pItems_: 아이템 객체들을 저장할 동적 배열을 가리키는 포인터입니다.new T[]를 통해 메모리를 할당받습니다.int capacity_: 인벤토리가 최대로 저장할 수 있는 공간의 크기입니다.int size_: 현재 인벤토리에 저장된 아이템의 실제 개수입니다.
생성자, 소멸자
- 생성자:
Inventory(int capacity = 10)- 인벤토리 객체가 생성될 때 호출됩니다.
- 매개변수로 인벤토리의 용량(
capacity)을 받으며, 값을 전달하지 않으면 기본값으로 10이 설정됩니다. - 안정성을 위해, 만약 0 이하의
capacity값이 들어오면 최소 용량을 1로 보정합니다. new T[capacity_]를 실행하여 아이템을 저장할 메모리 공간을 힙(Heap)에 할당합니다.
- 소멸자:
~Inventory()- 인벤토리 객체가 소멸될 때 (예:
main함수 종료 시) 자동으로 호출됩니다. delete[] pItems_를 실행하여 생성자에서 할당했던 메모리를 반드시 해제합니다. 메모리 누수(Memory Leak)를 방지하는 중요한 역할을 합니다.- 안전한 코드를 위해, 메모리 해제 후 포인터를
nullptr로 초기화합니다. 멤버 함수 (public)
- 인벤토리 객체가 소멸될 때 (예:
외부에서 인벤토리 객체를 조작하기 위해 사용하는 기능들입니다.
void AddItem(const T& item)- 새로운 아이템을 인벤토리에 추가합니다.
size_가capacity_보다 작을 경우에만 아이템을 추가하고,size_를 1 증가시킵니다.- 인벤토리가 꽉 찼다면 "인벤토리가 꽉 찼습니다!" 메시지를 출력하고 아무 동작도 하지 않습니다.
void RemoveLastItem()- 인벤토리의 가장 마지막에 추가된 아이템을 제거합니다.
- 실제로 메모리를 지우는 것이 아니라, 아이템의 개수를 나타내는
size_를 1 감소시켜 마지막 아이템에 접근할 수 없도록 만듭니다. - 인벤토리가 비어있다면 "인벤토리가 비어있습니다." 메시지를 출력합니다.
int GetSize() const- 현재 인벤토리에 저장된 아이템의 개수(
size_)를 반환합니다.
- 현재 인벤토리에 저장된 아이템의 개수(
int GetCapacity() const- 인벤토리의 최대 저장 용량(
capacity_)을 반환합니다.
- 인벤토리의 최대 저장 용량(
void PrintAllItems() const- 인벤토리에 있는 모든 아이템의 정보를 화면에 출력합니다.
for반복문을 이용해0번 인덱스부터size_ - 1번 인덱스까지 순회하며, 각 아이템 객체의PrintInfo()멤버 함수를 호출합니다.- 만약 인벤토리가 비어있다면 "(비어있음)" 메시지를 출력합니다.
// 정보를 출력하는 멤버 함수
void PrintInfo() const {
cout << "[이름: " << name_ << ", 가격: " << price_ << "G]" << endl;
}
구현을 한 뒤에 클래스의 구조는 아래와 같습니다.
- 복사 생성자 및 대입(Assign) 함수 구현:
- 인벤토리가 복사/대입될 때, 아이템 데이터가 그대로 복사되는 깊은 복사(Deep Copy)를 구현합니다.
Inventory(const Inventory<T>& other);(복사 생성자)- 객체가 생성+초기화될 때 호출
void Assign(const Inventory<T>& other);(대입 역할을 하는 함수)- 이미 존재하는 객체에 값을 덮어쓸 때 호출
// 복사 생성자
Inventory(const Inventory<T>& other) {
capacity_ = other.capacity_;
size_ = other.size_;
pItems_ = new T[capacity_];
for (int i = 0; i < size_; ++i) {
pItems_[i] = other.pItems_[i];
}
cout << "인벤토리 복사 완료" << endl;
}
AddItem기능 확장:- 인벤토리가 꽉 찬 상태에서
AddItem이 호출되면, 기존capacity의 2배 크기로 인벤토리를 확장하고 새로운 아이템을 추가합니다. (기존 아이템들은 모두 유지되어야 합니다.)
- 인벤토리가 꽉 찬 상태에서
Resize멤버 함수 추가:void Resize(int newCapacity): 인벤토리의capacity를newCapacity로 변경합니다.
SortItems멤버 함수 추가:void SortItems(): 인벤토리의 아이템들을 가격 오름차순으로 정렬합니다. 이 기능은 C++ 표준 라이브러리의std::sort알고리즘을 활용하며, 정렬 기준을 정의하기 위해 클래스 외부에 별도로 작성된 비교 함수(compareItemsByPrice)를std::sort에 전달합니다.
//두 Item 객체를 받아 가격을 기준으로 어떤 것이 먼저 와야 하는지 판단
bool compareItemsByPrice(const Item& a, const Item& b) {
return a.GetPrice() < b.GetPrice();
}