요약

추상화: 사물의 동작과 기능을 추출하여 표현하는 것

상속성: 기본 클래스를 바탕으로 새로운 기능을 추가한 새로운 클래스를 정의하는 것

다형성: 똑같은 호출이라도 상황에 따라, 호출하는 객체에 따라 다른 동작을 할 수 있는 능력


추상화

추상화(Abstraction)

  • “표현한다”
  • 사물의 동작과 기능을 추출하여 표현하는 것
  • 현실의 사물을 객체로 표현하기 위해 => 이 사물이 어떤 특징을 가지며 어떤 동작이 가능한지 데이터 모델링
  • 모델링의 결과 필요한 자료와 동작을 선택적으로 작성
  • 객체의 효율적이고 안전한 사용을 위해 구현부와 인터페이스를 분리


상속

상속성(Inheritance)

  • “재사용한다”
  • 기본 클래스를 바탕으로 새로운 기능을 추가한 새로운 클래스를 정의하는 것
  • 기본 클래스의 모든 속성과 동작을 물려받으며 필요한 기능을 추가하거나, 필요없는 기능을 변경함
  • 기존 객체를 최대한 재활용함으로써 시간과 노력을 절약
  • 기본 클래스 == 부모 클래스
  • 파생 클래스 == 자식 클래스


다형성

다형성(Polymorphism)

  • “상황에 따라 달라진다”
  • 똑같은 호출이라도 상황에 따라, 호출하는 객체에 따라 다른 동작을 할 수 있는 능력
  • 실제 내부 구현은 다르더라도 개념적으로 동일한 동작을 하는 함수를 하나의 인터페이스로 호출
  • 다형성은 동적 바인딩을 하는 가상 함수에 의해 구현됨


적용 실습1 - 플레이어, 몬스터

간단한 게임에서 플레이어, 몬스터를 만드려고 한다.

추상화

  • 우리 게임에는 어떤 속성이 필요할까? 체력? 공격력?…
  • 필요한 속성과 기능 리스트를 뽑는다.
    • 이름, 체력, 공격력, 입력키, 몬스터 등급, 정보출력…
  • 지금 생각나는 대부분의 파라미터가 플레이어와 몬스터와 중첩된다.

상속

  • 기본 클래스에서 중첩되는 속성을 정의하고, 플레이어나 몬스터 각각의 고유한 특성만 파생 클래스를 추가해 사용하자.
  • unit(기본 클래스) - 체력, 공격력, 정보출력…
    • player(파생 클래스) - 입력키,…
    • monster(파생 클래스) - 몬스터 등급,…

다형성

  • 플레이어와 몬스터는 다른 멤버변수를 가지고 있기 때문에, ‘정보출력’이 조금씩 다르다.
  • 공통되는 ‘정보출력’은 unit에서 정의하고,
  • 차이나는 ‘정보출력’은 player와 monster에서 재정의하자.
#include <iostream>
#include <vector>
using namespace std;

class Unit
{
protected:
	string name;
	int hp;
	int atk;
public:
	Unit() = default;
	Unit(string _name, int _hp, int _atk) :
		name(_name), hp(_hp), atk(_atk) {}
	virtual ~Unit() {}
public:
	virtual void PrintInfo()	// virtual 키워드: 파생 클래스에서 재정의를 예약
	{
		cout << "name: " << name << '\n';
		cout << "hp: " << hp << '\n';
		cout << "atk: " << atk << '\n';
	}
};

class Player : public Unit	// 상속
{
private:
	int pressedKey;
public:
	Player() = default;
	Player(string _name, int _hp, int _atk, int _pressedKey) :
		Unit(_name, _hp, _atk), pressedKey(_pressedKey) {}
	virtual ~Player() {}
	void PrintInfo() override	// 가상함수. 재정의되는 함수. override 키워드로 재정의했음을 명시
	{
		Unit::PrintInfo();	// 기본 클래스 함수 사용
		cout << "pressedKey: " << pressedKey << "\n\n";
	}
};

class Monster : public Unit	// 상속
{
private:
	int monsterGrade;
public:
	Monster() = default;
	Monster(string _name, int _hp, int _atk, int _monsterGrade) :
		Unit(_name, _hp, _atk), monsterGrade(_monsterGrade) {}
	virtual ~Monster() {}
	void PrintInfo() override   // 가상함수. 재정의되는 함수. override 키워드로 재정의했음을 명시
	{
		Unit::PrintInfo();	// 기본 클래스 함수 사용
		cout << "monsterGrade: " << monsterGrade << "\n\n";
	}
};

int main()
{
	Unit* player  = new Player("플레이어", 100, 10, 1);	// 생성
	Unit* monster = new Monster("몬스터", 50, 5, 3);
	player->PrintInfo();	// 가상함수 호출
	monster->PrintInfo();

	delete player;	// 메모리 해제
	delete monster;
	_CrtDumpMemoryLeaks();	// 메모리 누수 체크
}

name: 플레이어
hp: 100
atk: 10
pressedKey: 1

name: 몬스터
hp: 50
atk: 5
monsterGrade: 3


적용 실습2 - 슛골인 게임

간단한 슛 골인 게임을 만들며 최대한 상속과 다형성을 활용해봄


image


위와 같이 클래스를 나누고 필요한 기능과 동작을 뽑은 뒤 (추상화)

공통된 부분은 기본 클래스로, 차이나는 부분은 파생 클래스로 재정의하여 (상속성)

init, update, render, release 기능을 가상 함수로 구현 (다형성)


※ 틀리거나 개선할 부분이 있다면 알려주세요.

태그:

카테고리:

업데이트:

댓글남기기