#include
#include <iostream> // cout, cin, endl
#include <string> // string 문자열 자료형
#include <vector> // vector 동적 배열
#include <algorithm>// sort, min
#include <map> // key-value 저장소
using namespace std;
using namespace std;
// std를 안썼을때
std::cout << "hello";
std::string name;
// std를 썼을때
cout << "hello";
string name;
C++ 표준 라이브러리의 기능들은 원래 std::cout, std::string처럼 써야 함.
그런데 이 문장을 쓰면 std::를 생략할 수 있음.
템플릿 template<typename T> — 자료형을 일반화
template<typename T> //여기서 T는 “아직 정해지지 않은 타입”.
class Inventory
{
...
};
Inventory<Item> inventory(10); // 예시코드
템플릿은 자료형을 나중에 정하게 하는 문법.
이걸 통해 하나의 클래스로 여러 타입을 처리하는 방법을 알수잇음.
클래스 class - 사용자 정의 자료형
class Player
{
protected:
string name;
string job;
int level;
int exp;
int maxExp;
int hp;
int mp;
int power;
int defence;
...
};
클래스는 데이터와 기능을 하나로 묶는 문법
- 데이터: 이름, 직업, HP, MP, 공격력
- 기능: 공격, 상태 출력, getter, setter
접근 지정자 private, protected, public
private: // 클래스 내부에서만 사용
T* pItems;
int capacity_;
int size_;
protected: // 클래스 내부 + 자식 클래스
string name;
string job;
public: // 외부에서도 사용 가능
Player(string name, int hp, int mp, int power, int defence)
- Inventory 내부 배열은 외부가 함부로 건드리면 안 되니까 private
- Player의 이름/직업은 자식 클래스(전사, 궁수)가 써야 하니까 protected
- 생성자, getter, setter는 외부에서 써야 하니까 public
생성자 - 객체가 만들어질 때 자동 실행
Player(string name, int hp, int mp, int power, int defence)
{
this->name = name;
this->job = "None";
this->level = 1;
this->exp = 0;
this->maxExp = 100;
this->hp = hp;
this->mp = mp;
this->power = power;
this->defence = defence;
}
생성자는 객체를 만들 때 자동으로 호출되는 함수야.
역할
플레이어 객체가 만들어지면:
- 이름 저장
- 초기 직업 설정
- 레벨 1 설정
- 경험치 0 설정
- 기본 스탯 저장
이런 초기화 작업을 해줌.
this-> -- 현재 객체 자신 가리키기
this->name = name;
this->hp = hp;
this는 현재 객체 자신을 가리키는 포인터.
매개변수 이름과 멤버변수 이름이 같아서 구분하려고 씀.
상속 : public Player
class Warrior : public Player
{
public:
Warrior(string name, int hp, int mp, int power, int defence)
: Player(name, hp, mp, power, defence)
{
job = "전사";
this->hp += 30;
}
void attack(Monster* monster) override;
};
상속은 기존 클래스의 기능을 물려받아 새 클래스를 만드는 문법.
생성자 초기화 리스트 : Player(...)
Warrior(string name, int hp, int mp, int power, int defence)
: Player(name, hp, mp, power, defence)
{
...
}
자식 클래스가 만들어질 때, 먼저 부모 클래스 생성자를 호출하는 문법.
전사를 만들기 전에 먼저 Player 부분을 초기화하고,
그 다음에 전사 전용 설정을 추가한다.
가상 함수와 순수 가상 함수
virtual void attack(Monster* monster) = 0;
순수 가상 함수.
부모 클래스에서는 형태만 정하고, 구현은 자식이 꼭 하게 만드는 문법.
Player는 “플레이어는 공격할 수 있다”는 틀만 제공하고,
실제 공격 방식은 전사/마법사/도적/궁수가 각자 구현.
오버라이딩 override
void attack(Monster* monster) override; // 예시코드
void Archer::attack(Monster* monster)
{
int damage = (power - monster->getDefence()) / 3;
...
}
오버라이딩은 부모 클래스의 함수를 자식 클래스가 다르게 다시 구현.
- 전사: 한 번 강하게
- 마법사: 한 번 강하게
- 궁수: 3번 나눠 때림
- 도적: 5번 나눠 때림
같은 attack인데 행동이 다르다.
전방 선언 class Monster;
class Monster;
이건 “Monster라는 클래스가 뒤에 나올 거다”라고 미리 이름만 알려주는 문법.
왜 필요한가?
virtual void attack(Monster* monster) = 0;
player 안에서 위의 코드가있음
그런데 Monster 클래스 정의는 뒤쪽에 있기때문에
컴파일러에게 “Monster라는 타입이 나중에 나와”라고 미리 알려줘야 한다.
포인터 T*, Player*, Monster*
T* pItems; // 아이템 배열의 시작 주소
Player* player = nullptr; // 플레이어 객체를 가리키는 주소
virtual void attack(Monster* monster) = 0; // 몬스터 객체를 가리키는 주소
포인터는 메모리 주소를 저장하는 변수.
- 동적 메모리 할당
- 함수에 원본 객체 전달
- 부모 포인터로 자식 객체 다루기
동적 메모리 new, delete[], delete
pItems = new T[capacity_];
delete[] pItems;
player = new Warrior(name, stat[0], stat[1], stat[2], stat[3]);
...
delete player;
프로그램 실행중에 메모리를 직접 만들고 해제하는 문법.
- new T[capacity_] : 배열 생성
- delete[] pItems : 배열 해제
- new Warrior(...) : 객체 1개 생성
- delete player : 객체 1개 해제
소멸자 ~Inventory()
~Inventory()
{
delete[] pItems;
}
소멸자는 객체가 사라질 때 자동 호출되는 함수.
Inventory가 사라질 때 내부에서 new[]로 만든 메모리를 정리한다.
복사 생성자
Inventory(const Inventory& other)
{
capacity_ = other.capacity_;
size_ = other.size_;
pItems = new T[capacity_];
for (int i = 0; i < size_; i++)
{
pItems[i] = other.pItems[i];
}
}
복사 생성자는 객체를 복사해서 새 객체를 만들 때 호출되는 함수.
Inventory는 내부에 포인터 pItems가 있어서,
그냥 복사하면 주소만 복사되는 얕은 복사 문제가 생길 수 있음.
그래서 새 메모리를 만들고, 안의 값들을 직접 복사해야함.
배열과 인덱스
int stat[SIZE] = { 0 };
cout << "HP: " << stat[0] << " MP: " << stat[1] << endl;
cout << "공격력: " << stat[2] << " 방어력: " << stat[3] << endl;
배열은 같은 타입의 데이터를 순서대로 저장하는 구조.
함수 매개변수와 반환값
int GetStock(map<string, int>& potionStock, string name)
{
return potionStock[name];
}
함수는 입력을 받고 결과를 돌려줄 수 있음.
참조 & 와 포인터 * 차이
// 예시1
int GetStock(map<string, int>& potionStock, string name)
// 예시2
void setPotion(int count, int* p_HPPotion, int* p_MPPotion)
{
*p_HPPotion = count;
*p_MPPotion = count;
}
둘 다 원본에 접근할 수 있지만 다르다.
- 참조 & : 원본의 다른 이름처럼 사용
- 포인터 * : 주소를 받아서 역참조해서 사용
둘다나오는 이유
- map은 참조로 넘겨서 편하게 수정/조회
- 포션 숫자는 포인터로 넘겨서 주소 개념 연습
getter / setter
int getHP()
{
return hp;
}
void setHP(int hp)
{
this->hp = hp;
}
클래스 내부 데이터를 직접 열어두지 않고,
함수를 통해 읽고 수정하는 방법.
- 외부가 내부 구조를 직접 건드리지 않음
- 나중에 검증 로직 추가 가능
- 캡슐화 강화
구조체 struct
struct Item
{
string name;
int price;
void PrintInfo() const
{
cout << name << " (" << price << "G)" << endl;
}
};
// 또는
struct PotionRecipe
{
string potionName;
string ingredient1;
string ingredient2;
};
구조체는 관련 있는 데이터를 묶는 자료형.
C++에서는 함수도 넣을 수 있어서 class와 비슷하게 쓸 수 있음.
- Item : 아이템 정보
- PotionRecipe : 포션 레시피 정보
- DungeonRoom : 방 정보
const - 수정 금지 약속
void PrintInfo() const
void ShowAllRecipes(const vector<PotionRecipe>& recipes)
const는 “이걸 수정하지 않겠다”는 약속이야.
- PrintInfo() const : 이 함수는 객체의 멤버값을 바꾸지 않음
- const vector<PotionRecipe>& : recipes를 읽기만 하고 수정하지 않음
vector — 동적 배열
vector<PotionRecipe> recipes;
recipes.push_back({ "HP포션", "허브", "맑은물" });
vector는 크기가 자동으로 늘어나는 배열.
포션 레시피 개수가 고정이 아니어도 편하게 추가할 수 있음.
map<string, int> — key-value 자료구조
map<string, int> potionStock;
potionStock["HP 포션"] = 3;
potionStock["MP 포션"] = 3;
map은 이름표(key) 와 값(value) 를 짝으로 저장하는 자료구조.
반복문 for, while
for (int i = 0; i < size_; i++)
{
pItems[i] = other.pItems[i];
}
while (true)
{
...
}
- for : 횟수가 명확할 때
- while : 조건이 참인 동안 반복할 때
예시
- for : 인벤토리 복사, 배열 출력, 방 순회
- while : 게임 메뉴 반복, 전투 반복, 입력 검증
조건문 if, else if, switch
if (damage <= 0)
{
damage = 1;
}
switch (jobChoice)
{
case 1:
player = new Warrior(...);
break;
...
}
조건에 따라 분기하는 문법이야.
- if : 범위, 비교, 복합 조건에 강함
- switch : 번호 선택 메뉴에 적합
sort, min — 알고리즘 함수
sort(pItems, pItems + size_, compareByPrice);
int newHP = min(player->getHP() + 50, 100);
표준 라이브러리 알고리즘을 직접 사용하는 방법이야.
- sort : 정렬
- min : 둘 중 작은 값
예시
- 아이템 가격순 정렬
- HP/MP가 최대값을 넘지 않게 제한
'본캠프' 카테고리의 다른 글
| 5/8 (코드카타) (0) | 2026.05.08 |
|---|---|
| 5/7 (코드카타) (0) | 2026.05.07 |
| 5/6 (개인프로젝트,과제2도전step8) (0) | 2026.05.06 |
| 4/30(코드카타) (0) | 2026.04.30 |
| 던전탈출rpg과제 총정리+학습 (0) | 2026.04.29 |