C++
C++ 가상함수 테이블
Leesh96
2023. 4. 12. 15:48
오버라이딩(Overriding)
상속받은 함수를 자식 클래스에서 새로 정의하는 것
리턴 타입과 함수 인자 구성이 똑같아야 한다.
class Parent
{
void show()
{
cout << "this is parent\n" << endl;
}
}
class Child : public Parent
{
void show()
{
cout << "this is child\n" << endl;
}
}
class ChildChild : public Child
{
void show()
{
cout << "this is childchild\n" << endl;
}
}
int main()
{
Parent * p = new Parent;
Child * c = new Child;
ChildChild * cc = newChildChild;
p->show(); // 출력값 : this is parent
c->show(); // 출력값 : this is child
cc->show(); // 출력값 : this is childchild
p = c;
p->show(); // 출력값 : this is parent
p = cc;
p->show(); // 출력값 : this is parent
}
Parent 타입으로 선언된 p 포인터 변수에 Child 객체의 주소를 넣고, 함수를 호출하면 Child 객체의 함수가 호출되는 것이 아니라 Parent 클래스에 정의되어 있는 show() 함수가 호출된다.
단순히 함수를 오버라이딩할 경우, Parent 타입의 p 포인터 변수에 Child 객체 주소를 넣더라도 컴파일러는 p 변수가 Parent 타입이기 때문에 p 변수에는 Parent의 show() 함수가 바인딩된 상태로 빌드가 끝나버린다는 것이다.
빌드된 바이너리를 실행하면 바인딩된 상태로 실행되기 때문에 Parent 타입의 변수에 다른 객체를 넣더라도, Parent의 함수가 호출되는 것이다.
virtual이라는 키워드를 함 수 선언 시 붙임으로 가상함수라는 것을 만들어서 해결가능하다.
컴파일 시 가상함수가 정의된 클래스가 있다면 가상함수테이블이 만들어져서 'rdata'영역에 기록되며, 해당 클래스로 만들어진 객체에서 함수를 호출할 때 해당 클래스의 가상함수 테이블을 참조해서 호출한다.