Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++ 파생 클래스의 가상 함수(Virtual Function) 이해하기

C++에서 가상 함수(virtual function)는 기반 클래스(base class) 포인터 목록을 만들어, 실제 객체가 어떤 파생 클래스(derived class)에 속하는지 알지 못한 채로도 해당 파생 클래스의 메서드를 호출할 수 있게 해주는 강력한 기능입니다. 이러한 가상 함수는 컴파일 시점이 아닌 런타임(runtime)에 늦은 바인딩(late binding) 방식으로 해석됩니다.

가상 함수의 상속 규칙

기반 클래스에서 한 번 가상 함수로 선언된 멤버 함수는, 그 기반 클래스로부터 파생되는 모든 클래스에서 자동으로 가상 함수가 됩니다. 따라서 파생 클래스에서 가상 함수를 재정의(redefine)할 때는 virtual 키워드를 다시 붙일 필요가 없습니다.

이 규칙 덕분에 코드를 더 간결하게 유지할 수 있으며, 다형성(polymorphism)을 활용한 설계가 한층 수월해집니다.

예제 코드

#include<iostream>
using namespace std;

class B {
public:
    virtual void s() {
        cout << " In Base \n";
    }
};

class D : public B {
public:
    void s() { // virtual 키워드 없이 재정의 가능
        cout << "In Derived \n";
    }
};

int main(void) {
    D d;          // D 클래스의 객체 생성
    B *b = &d;    // B* 타입 포인터가 d를 가리킴
    b->s();       // 런타임에 D::s() 호출 결정
    return 0;
}

실행 결과

In Derived

코드 설명

위 예제에서 포인터 b는 타입이 B*임에도 불구하고, 실제로 가리키는 객체는 D 클래스의 인스턴스입니다. 함수 s()가 기반 클래스에서 virtual로 선언되었기 때문에, 호출 시점에 객체의 실제 타입을 기준으로 D::s()가 실행됩니다.

만약 virtual 키워드가 없었다면 포인터의 정적 타입을 따라 B::s()가 호출되었을 것입니다. 이것이 바로 가상 함수가 제공하는 동적 디스패치(dynamic dispatch)의 핵심입니다.

정리

  • 기반 클래스에서 virtual로 선언된 함수는 모든 파생 클래스에서 자동으로 가상 함수가 됩니다.
  • 파생 클래스에서 재정의 시 virtual 키워드는 생략할 수 있습니다(붙여도 무방하며, 가독성을 위해 명시하기도 합니다).
  • 기반 클래스 포인터나 참조를 통해 호출하면 런타임에 실제 객체 타입에 맞는 함수가 실행됩니다.