[C++] 다형성, 가상함수 테이블, 순수 가상함수, 추상 클래스
다형성
인프런 Rookiss님의 'Part1: C++ 프로그래밍 입문' 강의를 기반으로 정리한 필기입니다.
😎[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 강의 들으러 가기!
바인딩(Binding) - 정적 바인딩, 동적 바인딩
바인딩(Binding) = 묶는다.
정적 바인딩(Static Binding) | 컴파일 시점에 결정 |
동적 바인딩(Dynamic Binding) | 실행 시점에 결정 |
일반 함수는 정적 바인딩을 사용한다.
동적 바인딩을 원한다면?
- 가상 함수(virtual function)를 사용한다.
가상 함수 테이블 ( vftable )
그런데 실제 객체가 어떤 타입인지 어떻게 알고 알아서 가상함수를 호출해준걸까?
- 가상 함수 테이블 (vftable)
.vftable [] 4바이트(32비트 프로그램) 8바이트(64비트 프로그램)
[VMove] [VDie]
순수 가상함수, 추상 클래스
순수 가상 함수 : 구현은 없고, '인터페이스'만 전달하는 용도로 사용하고 싶을 경우
추상 클래스 : 순수 가상 함수가 1개 이상 포함되면 바로 추상 클래스로 간주
- 직접적으로 객체를 만들 수 없게 됨
- 아래의 경우 : Player클래스는 추상 클래스가 된다. 메인 함수에서 Knight클래스없이 Player클래스만 독립적으로 존재할 수 없다.
코드
#include <iostream>
using namespace std;
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; }
virtual void VAttack() = 0; // 순수 가상 함수
public:
int _hp;
};
class Knight : public Player // public Player. public 안 적으면 private으로 인식
{
public:
Knight()
{
_stamina = 100;
}
public:
void Move() { cout << "Move Knight! " << endl; } // 재정의.
// 가상 함수는 재정의를 하더라도 가상 함수다!
virtual void VMove() { cout << "VMove Knight! " << endl; }
virtual void VDie() { cout << "VDie Knight! " << endl; }
virtual void VAttack() { cout << "VAttack Knight! " << endl; }
public:
int _stamina;
};
class Mage : public Player
{
public:
int _mp;
};
// [ [ Player ] ]
// [ Knight ]
void MovePlayer(Player* player)
{
player->VMove();
player->VDie();
}
//void MoveKnight(Knight* knight)
//{
// knight->Move();
//}
int main()
{
Player p;
Knight k;
MovePlayer(&k); // Knight는 Player다? YES // 자식 클래스에서 부모 클래스로 넘어가는건 자연스럽다
return 0;
}
실행과정 Breakdown
void MovePlayer(Player* player)
{
player->VMove();
player->VDie();
}
MovePlayer 함수로 들어온 player의 주소를 까서 확인해보면
- 3개의 주소가 있다.
- Player의 첫번째 주소에는 vftable의 주소가 있다.
- Player의 두번째, 세번째 주소는 player->VMove()와 player->VDie()에 사용하는 player의 주소다.
- player의 포인터를 타고 eax에 들어간다. eax에 들어가는 데이터는 player에 저장된 주소(=3개의 주소: vftable의 주소 + player의 주소 2개)다.
- eax의 첫번째 값(=vftable의 주소 = 00b49b60)을 edx에 꺼내온다.
- edx값을 eax에 넘겨준다.
- call eax를 한다.
Knight 생성자의 선처리 부분
Knight 생성자의 선처리 부분
- 자기 자신의 vftable을 채워준다.
0939B60h을 타고가면 Knight의 VMove 함수와 VDie 함수 주소가 나온다.
'⭐ Programming > C++' 카테고리의 다른 글
[C++] 연산자의 오버로딩 (Operator Overloading), 오버로딩 vs 오버라이딩 (0) | 2022.04.05 |
---|---|
[C++] 초기화 리스트 (0) | 2022.04.05 |
[C++] 다형성 (Polymorphism) (0) | 2022.04.05 |
[C++] 은닉성 (0) | 2022.04.04 |
[C++] 상속성 (0) | 2022.04.04 |
댓글
이 글 공유하기
다른 글
-
[C++] 연산자의 오버로딩 (Operator Overloading), 오버로딩 vs 오버라이딩
[C++] 연산자의 오버로딩 (Operator Overloading), 오버로딩 vs 오버라이딩
2022.04.05 -
[C++] 초기화 리스트
[C++] 초기화 리스트
2022.04.05 -
[C++] 다형성 (Polymorphism)
[C++] 다형성 (Polymorphism)
2022.04.05 -
[C++] 은닉성
[C++] 은닉성
2022.04.04