프로그래밍 언어/C++
C++(17) 다형성 - 1
KJ1111
2023. 9. 15. 13:52
728x90
다형성에서 중요한 부분은 동적 바인딩이다. 이전에 정적 바인딩은 Compile-time 에서 어떤 함수를 호출할 지 정하는 것을 정적 바인딩이라고 한다. 동적 바인딩은 Run-time에서 어떤 함수를 실행하는지 정하는 것이다. 런타임 다형성은 런타임에서 같은 함수에 대해 다른 의미를 부여하는 것이고 이것을 함수의 오버라이딩이라고 한다. 동적 바인딩의 조건은 3가지 있다.
- 상속
- 기본 클래스 포인터 또는 참조자
- 가상 함수
정적 바인딩은 컴파일시 타입을 기준으로 호출 함수를 결정하지만, 동적 바인딩은 런타임시 실제 메모리에 저장된 타입을 기준으로 호출 함수를 결정한다.
유도 클래스에서 기본 클래스의 함수를 재정의 또는 오버라이드해 사용할 수 있다. 오버라이드된 함수는 동적 바인딩을 통해 활용 가능하다. 오버라이드 될 수 있는 함수를 가상함수라고 한다.
#include <iostream>
class Entity
{
protected:
int x, y;
public:
Entity(int x, int y)
: x{ x }, y{ y } {}
virtual void Move(int dx, int dy)
{
x += dx;
y += dy;
}
void PrintPosition()
{
std::cout << x << "," << y << std::endl;
}
};
class Player : public Entity
{
private:
int hp;
int xp;
public:
Player(int x, int y, int hp, int xp)
: Entity{ x, y }, hp{ hp }, xp{ xp } {}
virtual void Move(int dx, int dy)
{
x += dx * 2;
y += dy * 2;
}
};
int main()
{
Entity* e = new Player{ 1, 1, 10, 10 };
e->PrintPosition();
e->Move(2, 1);
e->PrintPosition();
delete e;
return 0;
}
가상함수를 만들려면, 기본 클래스의 함수에 virtual 키워드를 앞에 작성한다. 유도 클래스에서 가상함수로 만들려는 함수에 virtual 키워드르 이 함수가 붙이면 오버라이드 된 함수임을 좀더 보기 명확해 진다. 만약 유도 클래스에서 함수를 오버라이드 하지 않을 경우 기본 클래스의 함수가 상속된다.
#include <iostream>
class Entity
{
protected:
int x, y;
public:
Entity(int x, int y)
: x{ x }, y{ y } {}
~Entity()
{
std::cout << "Entity Destructor Called" << std::endl;
}
virtual void Move(int dx, int dy)
{
x += dx;
y += dy;
}
void PrintPosition()
{
std::cout << x << "," << y << std::endl;
}
};
class Player : public Entity
{
private:
int hp;
int xp;
public:
Player(int x, int y, int hp, int xp)
: Entity{ x, y }, hp{ hp }, xp{ xp } {}
~Player()
{
std::cout << "Player Destructor Called" << std::endl;
}
virtual void Move(int dx, int dy)
{
x += dx * 2;
y += dy * 2;
}
};
int main()
{
Entity* e = new Player{ 1, 1, 10, 10 };
e->PrintPosition();
e->Move(2, 1);
e->PrintPosition();
delete e;
return 0;
}
// 출력
1,1
5,3
Entity Destructor Called
만약 기본 클래스의 소멸자를 가상함수로 지정하지 않을 경우 Entity의 소멸자만 호출된다.
virtual ~Entity()
{
std::cout << "Entity Destructor Called" << std::endl;
}
// 출력
1,1
5,3
Player Destructor Called
Entity Destructor Called
클래스가 가상함수를 가지면, 항상 가상 소멸자를 함께 정의해야 한다.