TextRPG OOP 1, 2, 3

CJB_ny·2022년 8월 17일
0

C++ 정리

목록 보기
58/95
post-thumbnail

객체 지향적으로 생각을 하자.

C#과 다르게 폴더 만들어도

가상 폴더 느낌임.

실제로는 한곳에 다 때려박혀있음.

MyPlayer p. MyPlayer* p

Game이라는 설계도를 만들때

11, 12 번째 줄은 완전히 다른 것이다.

MyPlayer player는 멤버 클래스로 들고있는 형태이고

MyPlayer* player2는 멤버 포인터를 들고있는 형태이다.

멤버클래스로 들고있는 경우 "생명주기" 관점에서

Game이라는 클래스에 너무 의존적이다.

이런식으로 멤버 클래스를 들고있는 것은 안좋은 설계 습관이다.

현재 상황은 Game을 설계 하기위해서는 MyPlayer가 반드시 있어야 한다는 것이다.

그래서 생각할점!

MyPlayer player 로 들고있다면

player의 정보가 5000바이트라고하면은 Game이라는 클래스 자체의 크기도 5000바이트 이상이 된다.

또한 MyPlayer를 상속받는 다른 객체를 못만든다.

상속받는 애들은 크기가 더 클 테니까

순환 구조 ❗

Player를 만들려먼 Game을 알아야해서 Game.h inlcude하고

Game을 만들려면 Player알아야해서 include Player.h를 해버려서

빌드하면 에러 생긴다.

그래서 이런 순환구조가 있을 경우에는

더더욱 멤버 클래스가 아닌, Player* player 포인터로 들고있는 것을 생각해야한다.

전방 선언

이런 멤버 포인터를 가지고있는 경우 주소바구니를 하나 들고있는 것이기 때문에

Player의 설계도가 (헤더파일이) 굳이 설계가 되어 있지 않는다고 하더라도

Game 이라는 클래스의 설계는 완성이 될 수 있다는 말이다.

=> 즉, 이렇게하면은 include 하지 않더라도 설계가 완성이 되는데

지금 빨간줄이 뜨는 이유는 "전방 선언"을 안해주어서 그렇다.

즉, 이 Player라는 애가 나중에라도 완성이 될 것이라고 "안심"을 시켜 주어야한다.

이것을 "선언" 해야하는데 전방에 선언한다.

Game.cpp 설계

일단 이렇게 설계를 해주도록 하자.

< > 문법은 cpp에서 기본적으로 제공하는 라이브러리

" " 는 커스텀 한 것.

게임이라는 것이 대부분 초기화 화는 부분과 무한 반복문을 돌게된다.

보통 이런 구조를 가짐.

그래서 이것들을 구현하러 가보도록 하자.

#pragma once

// 전방 선언
class MyPlayer;
class Field;

// Is - A
// Has - A
class Game
{
private:

public :
	Game();
	~Game();

	void Init();
	void Update();
	void CreatePlayer();

public:
	MyPlayer* _player;
	Field* _field;
};

Monster 설계

항상 상속관계를 집중하면서 보도록 하자.

이게 상속이 어떻게 이루어 져있는지...

#pragma once
#include "Creature.h"

enum MonsterType
{
	MT_Slime = 1,
	MT_Orc = 2,
	MT_Skeleton = 3
};

class Monster : public Creature
{
public:
	Monster(int monsterType)
		:
		Creature(CT_Monster),
		_monsterType(monsterType)
	{

	}

public:
	int _monsterType;
};

class Slime : public Monster
{
public :
	Slime()
		:
		Monster(MT_Slime)
	{
		_hp = 50;
		_attack = 3;
		_defense = 2;
	}
};

class Orc : public Monster
{

public:
	Orc()
		:
		Monster(MT_Orc)
	{
		_hp = 80;
		_attack = 5;
		_defense = 3;
	}
};

class Skeleton : public Monster
{

public:
	Skeleton()
		:
		Monster(MT_Skeleton)
	{
		_hp = 100;
		_attack = 10;
		_defense = 5;
	}
};

실질적으로 동작 하는 부분

실질적으로 동작하는 부분에서는 #include를 통해서 라이브러리 가져와야한다.

.cpp같은 파일에서는

.h 헤더파일 같은 경우에는

"구현"만 해놓기 때문에 전방선언만 해놓으면된다.

추상함수 ❗

MyPlayer든 Monster든 각자의 info를 출력할 수 있게 하기 위하여

Creatrue 에다가

virtual void PrintInfo() = 0;

이렇게 선언 해주도록 하자.

이렇게 " = 0 " 을하게되면

가상함수는 가상함수인데 "추상적인 가상함수"가 되기 때문에

(순수 가상함수 == "인터페이스"만 전달하는 용도)

Creature를 상속받는 애들은 이것을 반드시 구현을 해야한다.

모던 C++에서는

  • virtual void VAttack() abstract;

일반 C++에서는

  • virtual void VAttack() = 0;

이렇게 순수 가상 함수가 하나라도 있을 경우

해당 클래스는 "추상 클래스"가 된다.

=> "재정의 해야하는 강제가 주어진다"


순수 가상함수 ==? 추상적인 가상함수 ?

(같은 말인가??)

https://velog.io/@starkshn/%EB%8B%A4%ED%98%95%EC%84%B1-1-2#virtual-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%B9%84%EA%B5%90


profile
https://cjbworld.tistory.com/ <- 이사중

0개의 댓글