가상 함수가 필요한 이유
#include <Windows.h>
class CPlayer {
public:
void ShowMe() {
std::cout << "CPlayer" << std::endl;
}
};
class CChild : public CPlayer {
public:
void ShowMe() {
std::cout << "CChild" << std::endl;
}
};
int main()
{
CPlayer* p = new CChild();
p->ShowMe();
return 1;
}
- C++은 데이터 타입을 기준으로 어떤 클래스의 함수를 호출할지를 결정 짓습니다. 그렇기 때문에 위와 같은 코드를 실행할 경우 p는 실질적으로 CChild 인스턴스를 가리키지만 CPlayer의 ShowMe 함수를 호출하게됩니다. 하지만, 가상 함수를 사용할 경우 데이터 타입이 아닌 인스턴스를 기준으로 어떤 함수를 호출할지 결정지을 수 있습니다.
가상 함수 사용법
#include <iostream>
#include <Windows.h>
class CPlayer {
public:
virtual void ShowMe() {
std::cout << "CPlayer" << std::endl;
}
};
class CChild : public CPlayer {
public:
virtual void ShowMe() override {
std::cout << "CChild" << std::endl;
}
};
int main()
{
CPlayer* p = new CChild();
p->ShowMe();
return 1;
}
- 가상 함수를 사용하려면 가상 함수로 정의할 멤버 함수에 virtual 키워드를 사용하면 됩니다. 그러면 해당 클래스를 상속 받은 클래스에서 가상 함수 오버 라이딩할 수 있으며, 컴파일러는 해당 가상 함수를 호출할 때 데이터 타입이 아닌 인스턴스에 있는 가상 함수 테이블 포인터를 참조하여 어떤 클래스의 가상 함수를 호출할지 결정 짓습니다.
- 부모 클래스에서 상속 받은 가상 함수를 오버라이딩 할 때 이후 자식 클래스에서 오버라이딩을 허용시키려면 override 키워드를 사용하고 이번 클래스가 마지막 오버라이딩이라면 final 키워드를 붙이면 됩니다.
순수 가상함수와 추상 클래스
class CPlayer {
public:
virtual void ShowMe() = 0;
};
class CChild : public CPlayer {
public:
virtual void ShowMe() {
std::cout << "CChild" << std::endl;
}
};
int main()
{
// 인스턴스와 불가
CPlayer a;
CPlayer* p = new CChild();
p->ShowMe();
return 1;
}
- 순수 가상함수란 가상 함수의 정의 대신 0을 대입하는 형태로 선언된 함수를 말합니다. 이렇게 순수 가상 함수가 선언된 클래스는 인스턴스화될 수 없는 오직 인터페이스 역할로만 사용할 수 있는 클래스입니다. 그리고 C++은 순수 가상함수를 가진 클래스를 "추상 클래스"라고 합니다.
가상 함수 테이블이란?
- 가상 함수 테이블은 컴파일러가 가상 함수를 가진 클래스를 컴파일하여 생성하는 가상함수 참조 테이블입니다. 그리고 가상 함수를 가진 클래스가 생성자가 호출되어 인스턴스화될 때 객체의 맨 앞에는 가상 함수 테이블 포인터가 셋팅됩니다.
생성자와 가상 함수 테이블
#include <iostream>
#include <Windows.h>
class CPlayer {
public:
virtual void ShowMe() = 0;
};
class CChild : public CPlayer {
public:
virtual void ShowMe() {
std::cout << "CChild" << std::endl;
}
};
int main()
{
CPlayer* p = static_cast<CPlayer*>(malloc(sizeof(CChild)));
p->ShowMe();
return 1;
}
- 가상 함수 테이블을 셋팅하려면 반드시 생성자가 호출되어야 합니다. 위와 같이 malloc으로 동적할당 후 가상 함수를 호출할 경우 가상 함수 테이블이 없기 때문에 참조 에러가 발생됩니다.
'Programming Language > C, C++' 카테고리의 다른 글
const와 constexpr(constant expression)의 차이점 (0) | 2023.02.27 |
---|---|
C++ 스마트 포인터( Smart Pointer ) 사용 방법 (0) | 2023.01.28 |
new와 malloc의 차이점 (0) | 2023.01.27 |
얕은 복사와 깊은 복사 (0) | 2023.01.27 |
C++의 RAII( Resource Acquisition Is Initialization ) 디자인 패턴이란 (0) | 2023.01.27 |