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'영역에 기록되며, 해당 클래스로 만들어진 객체에서 함수를 호출할 때 해당 클래스의 가상함수 테이블을 참조해서 호출한다.