[C++]_S16-5-다형성

신치우·2025년 3월 1일

CPP

목록 보기
49/62

다형성의 중요점
1. 오버로딩
2. 오버라이딩
3. 바인딩
4. 가상함수 테이블
5. 순수 가상함수
7. 추상클래스

#include <iostream>
using namespace std;
// 오늘의 주제 : 다형성

// 객체지향 (OOP Object Oriented Programming)
// - 상속성
// - 은닉성 = 캡슐화
// - 다형성

// 다형성 (Polymorphism = Poly + morph) = 겉은 똑같은데, 기능이 다르게 동작
// - 오버로딩(Overloading) = 함수 중복 정의 = 함수 이름의 재사용
// - 오버라이딩(Overriding) = 재정의 = 부모 클래스의 함수를 자식 클래스에서 재정의

// 바인딩(Binding) = 묶는다
// - 정적 바인딩(Static Binding) : 컴파일 시점에 결정
// - 동적 바인딩(Dynamic Binding) : 실행 시점에 결정

// 일반 함수는 정적바인딩을 사용하게 됨
// 동적 바인딩을 원한다면? -> 가상함수(virtual function)

// 그런데 실제 객체가 어떤 타입인지 어떻게 알고 가상함수를 호출해주는걸까?
// - 가상 함수 테이블(vftable)
// .vftable [] 4바이트(32) 8바이트(64)
// [VMove] [VDie]
// 가상함수 테이블은 생성자의 선처리 영역에서 세팅해줌

// 순수 가상 함수 : 구현은 없고 '인터페이스' 만 전달하는 용도로 사용하고 싶을 경우
// 추상 클래스 : 순수 가상 함수가 1개 이상 포함되면 바로 추상 클래스로 간주
// - 직접적으로 객체를 만들수 없게 됨
class Player
{
public:
	Player()
	{
		_hp = 100;
	}
	void Move() { cout << "Move Player !" << endl; }
	void Move(int a) { cout << "Move Player (int) !" << endl; } // 오버로딩
	virtual void VMove() { cout << "VMove Player !" << endl;  }
	virtual void VDie() { cout << "VDie Player !" << endl; }

	// 순수 가상 함수 -- 상속받은 애들이(Knight, Mage) 모두 VAttack()을 만들어서 사용해라 라고 압박
	virtual void VAttack() = 0; 

public:
	int _hp;
};

class Knight : public Player
{
public: 
	Knight()
	{
		_stamina = 100;
	}
	void Move() { cout << "Move Knight !" << endl; } // 오버라이딩

	// 가상함수는 재정의를 하더라도 가상 함수임.
	virtual void VMove() { cout << "VMove Knight !" << endl; } 
	void VDie() { cout << "VDie Knight !" << endl; }// virtual이 없어도 가상함수로 인식
	void VAttack() { cout << "VDie VAttack !" << endl; }
public:
	int _stamina;
};

class Mage : public Player
{
public:
	void VAttack() { cout << "VDie VAttack !" << endl; }
public:
	int _mana;
};

void MovePlayer(Player* player)
{
	// 정적 바인딩
	player->Move();
	
	// 동적 바인딩
	player->VMove(); // 이건 player의 Move함수 호출 --> 아무리 자식클래스를 타고 올라와도 부모클래스의 Move를 호출함
	player->VDie();
}

//void MoveKnight(Knight* knight)
//{
//	knight->Move();
//}

int main()
{
	// Player p; // 순수 가상 함수를 추가한 후에는 추상클래스가 됐기때문에 단독으로 사용할 수 없게 됨.
	// p.Move(); // 첫번째 Move 를 따라감
	// p.Move(100); // 두번째 Move를 따라감
	// MovePlayer(&p); // player가 플레이어? Yes
	// MoveKnight(&p); // error가 발생 --> player가 기사? No --> 부모클래스에서 자식클래스를 탐색하지 않음

	Knight k;
	k.Move();
	//MoveKnight(&k); // 기사는 기사다? Yes
	MovePlayer(&k); // 기사는 플레이어다? Yes error 발생 X --> 자식클래스는 부모클래스가 맞다라고 대답함
	// 위 내용을 이용하면 결국 모든 자식클래스가 가져야하는 것이라면 부모클래스를 이용해서 할 수 있다는 의미.
	// 하지만 가상함수를 사용한다면 자식클래스가 가지고 있는 VMove를 불러서 사용하게됨


	return 0;
}
profile
https://shin8037.tistory.com/

0개의 댓글