업 캐스팅 했을 때, 부모클래스 포인터가 자식클래스 객체를 가리키는 상황에서 함수를 호출하면 부모클래스의 함수가 호출되는 것을 확인했습니다. 이를 바로 해결하는 방법이 있습니다.
#include <iostream>
class Parent {
public:
Parent()
{
std::cout << "부모클래스 생성자" << std::endl;
}
~Parent()
{
std::cout << "부모클래스 소멸자" << std::endl;
}
virtual void test()
{
std::cout << "부모 test()" << std::endl;
}
};
class Child : public Parent{
public:
Child()
{
std::cout << "자식클래스 생성자" << std::endl;
}
~Child()
{
std::cout << "자식클래스 소멸자" << std::endl;
}
void test()
{
std::cout << "자식 test()" << std::endl;
}
};
int main()
{
Parent p;
Child c;
Parent* p_c = &c;
Parent* p_p = &p;
p_p->test();
p_c->test();
return 0;
}
위 코드를 실행하면
원래는 둘 다 부모 test()라고 나와야 정상이었습니다. 놀랍게도 각 포인터들이 무엇을 가리키는지 아는 것 처럼 적절한 test() 함수를 호출해준 것입니다. 이런 일이 가능해진 이유는 virtual 키워드 입니다.
컴파일러 입장에서, p_c는 부모클래스 포인터니까 부모클래스의 test()를 실행시켜야지 라고 했지만, test()가 virtual이기 때문에 실제 부모클래스 객체인지 확인하고 자식클래스 객체임을 확인한 다음 자식클래스의 test()를 실행한 것입니다.
이렇게 컴파일 시에 어떤 함수가 실행될지 정해지지 않고 런타임 시에 정해지는 일을 가리켜 동적 바인딩(dynamic binding)이라고 부릅니다.
동적 바인딩의 반대로 정적 바인딩(statiac binding)이 있는데 이는 컴파일 타임에 어떤 함수가 호출될 지 정해지는 것으로 여태까지 알고 있던 함수에 해당합니다.
덧붙여서, virtual 키워드가 붙은 함수를 가상 함수(virtual function)라고 부릅니다. 이렇게 파생 클래스의 함수가 기반 클래스의 함수를 오버라이드 하기 위해서는 두 함수의 꼴이 정확히 같아야 합니다.
이렇게 같은 함수를 호출했음에도 불구하고 어떤 경우는 부모클래스의 것이, 어떤 경우는 자식클래스의 것이 호출되는 일; 즉 하나의 메소드를 호출했음에도 불구하고 여러가지 다른 작업들을 하는 것을 바로 다형성(polymorphism)이라고 부릅니다.
'C++' 카테고리의 다른 글
상속과 가상 함수 (0) | 2020.10.29 |
---|---|
업 캐스팅과 다운 캐스팅 (0) | 2020.10.29 |
상속 (Inheritance) (0) | 2020.10.27 |
C++ 에서의 캐스팅(형변환) (0) | 2020.10.27 |
연산자 오버로딩(전위/후위 증감 연산자) (0) | 2020.10.27 |