728x90
반응형
virtual
virtual 키워드는 가상 함수를 선언할 때 사용하는 키워드이다.
가상함수는 상속받은 클래스에서 재정의할 수 있는 함수로 파생 클래스에서 재정의한 함수가 호출된다.
상속받은 클래스에서 기반 클래스의 함수를 다양하게 수정하거나 확장할 수 있다.
아래 코드를 살펴보자.
#include <iostream>
class Base {
public:
Base() { std::cout << "기반 클래스" << std::endl; }
virtual void what() { std::cout << "기반 클래스의 what()" << std::endl; }
};
class Derived : public Base {
public:
Derived() : Base() { std::cout << "파생 클래스" << std::endl; }
void what() { std::cout << "파생 클래스의 what()" << std::endl; }
};
int main() {
Base p;
Derived c;
Base* p_c = &c;
Base* p_p = &p;
std::cout << " == 실제 객체는 Base == " << std::endl;
p_p->what();
std::cout << " == 실제 객체는 Derived == " << std::endl;
p_c->what();
return 0;
}
실행 결과
p_p와 p_c 둘 다 Base 객체를 가리키는 포인터이다.
그래서 p_p->what()와 p_c->what()을 했을 때, "기반 클래스의 what()"이라고 출력이 되어야 했는데 결과는 그렇게 나오지 않았다.
p_p는 Base 객체를 가리키고 p_c는 Derived 객체를 가리키는 것에 따라 적절한 what() 함수를 호출하였다.
이는 virtual 키워드로 인해 가능한 일이다.
virtual 키워드는 다음과 같은 역할을 한다.
Derived c;
Base* p_c = &c;
p_c->what();
런타임 시, 컴퓨터는 p_c는 Base 포인터니까 Base의 what()을 실행해야 하는데 what() 함수가 virtual로 선언이 되어 있으므로 실제 객체가 어떤 객체인지 확인한다.
p_c는 실제로 Derived 객체이므로 Derived의 what()을 실행한다.
반면, 아래의 경우에는 p_p가 Base의 객체이므로 Base의 what()을 호출한다.
Base p;
Base* p_p = &p;
p_p->what();
이렇게 컴파일 시에 어떤 함수가 실행될 지 정해지지 않고, 런타임시에 정해지는 일을 동적 바인딩이라고 부른다.
728x90
반응형