TIL 2024/8/15

Sung Joo Lee·2024년 8월 15일

상속 pt.1


상속이 필요한 이유

  • 아래의 Player 코드가 있다
#include <iostream>

class Player
{
private:
	int x, y, speed;
public:

	Player(int x, int y, int speed)
		:x{x},y{y},speed{speed}
	{
	}

	void Move(int dx,int dy){
		x += dx * speed;
		y += dy * speed;
	}

	void ShowPosition() {
		std::cout << x << "," << std::endl;
	}
};

int main()
{
	Player p1{ 1,1,10 };
	Player p2{ 1,1,10 };
	Player p3{ 1,1,10 };

	return 0;
}

객체들이 많이 생성이 되었을 때 이를 관리하는 클래스 ( 컨트롤/매니저 클래스)가 필요하다

예시 코드

#include <iostream>

class Player
{
private:
	int x, y, speed;
public:
	
	Player() = default;//기본 생성자

	Player(int x, int y, int speed)
		:x{x},y{y},speed{speed}
	{
	}

	void Move(int dx,int dy){
		x += dx * speed;
		y += dy * speed;
	}

	void ShowPosition() {
		std::cout << x << "," << std::endl;
	}
};

class PlayerHandler
{
private:
	Player* playerList[50];
	int playerNum;
public:
	PlayerHandler() // 생성자
		:playerNum{0}
	{}

	void addPlayer(Player* p){ //p는 객체의 주소
		playerList[playerNum++] = p;
	}

	void showAllPlayerPosition() const
	{
		for (int i = 0; i < playerNum; i++) {
			playerList[i]->ShowPosition();
		}
	}

	~PlayerHandler() {
		for (int i = 0; i < playerNum; i++) {
			delete playerList[i]; //heap 영역 해제
		}
	}

};

int main()
{
	PlayerHandler playerHandler;
	playerHandler.addPlayer(new Player( 1,1,1 ));
	playerHandler.addPlayer(new Player(5, 5, 1));
	playerHandler.addPlayer(new Player(2, 3, 1));
	playerHandler.showAllPlayerPosition();

	return 0;
}
  • 위의 코드를 보면 playerHandler 객체로 player들을 관리한다.

상속이 필요한 이유, 시나리오

  • 만약 Player 이외에 Enemy와 NPC가 추가된다면?

  • Enemy와 NPC의 이동 방식이 다르다면?

    • Enemy : dx speed 1.5f
    • NPC : 이동 불가능
  • 이 때마다 새로운 Enemy, NPC class , 또 이를 관리하는 GameHandler를 작성해야 하지만 우리는 ‘상속’과 ‘다형성’을 사용하여 적은 수정으로 기능 추가 가능하도록 설계 가능하다.

상속의 정의

  • 미리 만들어져 있는 (코드) base class를 가져와서 그 위에 새로운 class를 만드는 것

  • 새로운 클래스는 기존 클래스의 데이터와 함수를 포함

  • 기존 클래스의 코드를 재활용 할 수 있다는 장점, 구조를 간결하게 할 수 있다.

  • 클래스들 간의 공통 속성에 집중하는 설계 방법

  • 기존 클래스의 함수를 수정하여, 새로운 클래스의 행동을 새로 정의 가능

    • 기존 클래스이 행동을 수정할 필요는 없음

예시 설계

내가 아래와 같이 게임에서 필요한 Player,Enemy , NonPlayer 클래스를 구상을 했을때

‘상속’을 사용하지 않으면 공통된 기능의 중복되는 코드들을 전부 따로 작성해줘야 한다.

  • 현재 X,Y, Talk() 가 공통된 기능이기 때문에
class Enitiy{
	//X,Y,Talk() 
};

class Player : public Enitiy{
		//speed,hp,xp,Move()
};

class Enemy : public Entitiy{
		//speed,hp,gold,Move()
};

class NonPlayer : public Entity{
		//dialog
};

위와 같이 공통 기능을 하는 class를 만든 후 상속을 하여, 해당 클래스를 기반으로 각각의 필요한 클래스를 만들 수 있다.

  • 이제 그림으로 확인해 보자

  • Player 객체는 두 가지 타입을 모두 가진 상태가 된다.
    • Player 객체는 Player 타입이기도 하지만 Entity 타입이기도 하다.

용어 정리

  • 기본 클래스 ( base class / parentclass)
    • 상속의 대상이 되는 클래스
  • 유도 클래스 ( derived class)
    • 기본 클래스로부터 생성되는 클래스
    • 데이터와 행동을 기본 클래스로부터 상속함
profile
개발로그

0개의 댓글