1. 다형성(Polymorphism)
외형은 같지만 기능은 다르게 동작한다.
(1) 오버로딩
함수를 중복 정의함(함수 이름 재사용)
class Player
{
public:
void Move() { cout << "Move Player" << endl;}
void Move(int a) { cout << "Move Player (int)" << endl;}
public:
int _Hp;
};
int main()
{
Player p;
p.Move();
p.Move(10);
return 0;
}
위처럼 int 인자를 받는 Move 함수와 아무런 인자가 없는 Move 함수를 선택하여 사용할 수 있다.
(2) 오버라이딩
부모 클래스(Player내의 Move)의 함수를 자식 클래스(Knight내의 Move)에서 재정의
class Knight : public Player
{
public:
void Move(int a) { cout << "Move Knight" << endl;}
public:
int _stamina;
};
2. 바인딩 / 자식 클래스의 함수 오버라이딩 문제
Player 안에 Knight와 Mage가 있고 자식의 멤버 함수를 오버라이딩 하고 Move 함수를 호출하면
Knight와 Mage는 Player의 상속을 받기 때문에 Player의 Move를 받음
Knight의 Move를 호출하도록하기 위해 동적 바인딩을 이용할 수 있음
바인딩 : 컴파일러가 프로그램 소스의 요소에 대해 값 또는 속성을 확정하는 것
(1) 정적 바인딩
컴파일 시점에 결정
일반적인 함수는 정적 바인딩을 사용
(2) 동적 바인딩
실행 시점에 결정
동적 바인딩을 원한다면 가상 함수를 사용할 수 있음
3. 동적 바인딩
(1) 가상 함수
class Player
{
public:
void Move() { cout << "Move Player" << endl;}
virtual void VMove() {cout << "Move Player" << endl;}
public:
int _Hp;
};
class Knight : public Player
{
public:
void Move(int a) { cout << "Move Knight" << endl;}
virtual void VMove() {cout << "Move Knight" << endl;}
public:
int _stamina;
};
// output : Move Knight
가상 함수를 사용하여 플레이어 내에서 만들고, 나이트 클래스 안에서 재정의를 했을 때 main 함수에서 호출하면
자식 클래스인 나이트 클래스의 오버라이딩된 함수 VMove를 호출하는 것을 알 수 있다.
(2) 가상 함수 테이블 (vf table)
가상 함수를 호출할 때 실제 객체의 타입에 맞는 함수가 호출되도록 한다.
1) 클래스에 가상 함수가 있다면 해당 클래스에 대한 가상 함수 테이블이 생성됨
2) 객체가 생성되면 해당 클래스의 가상 함수 테이블에 대한 포인터가 객채 내부에 저장됨
3) 가상 함수를 호출하면 가상 함수 테이블 포인터를 이용하여 객체 내의 가상 함수 테이블에 접근하고 함수의 포인터를 찾음
4) 원하는 함수의 포인터를 사용해 실제 함수를 호출
=> 자식 클래스에서 오버라이딩된 함수를 사용하게 됨
(3) 순수 가상 함수
부모 클래스 내에서 구현은 없고 인터페이스만 전달하는 용도로 사용할 때 사용함
추후에 자식 클래스에서 반드시 구현부분이 포함되어야 함
virtual void VAttack() = 0;
(4) 추상 클래스
순수 가상 함수가 1개 이상 포함된 클래스
직접적으로 객체를 만들 수 없게 됨 => 자식 클래스를 이용하여 간접적으로 객체를 만들 수 있음
'기초 C++ 스터디 > 객체지향' 카테고리의 다른 글
5-7. 객체지향 정리 (0) | 2023.05.30 |
---|---|
5-6. 연산자 오버로딩 (0) | 2023.05.30 |
5-5. 초기화 리스트 (0) | 2023.05.26 |
5-3. 은닉성 (0) | 2023.05.26 |
5-2. 상속성 (0) | 2023.05.26 |