Programming Language/C++

[C++] 가상 함수(Virtual Function)와 동적 바인딩(Dynamic Binding)

lumana 2024. 6. 27. 19:15

가상 함수(Virtual Function)와 동적 바인딩(Dynamic Binding)

  • 동적 바인딩 : 부모 클래스가 자식 클래스를 가리키고 있으면, 자식 클래스에 오버라이딩된 메서드를 실행할 수 있도록 동적으로 바인딩을 해준다.

  • 참고)

    • 동적 --> 런타임에 결정

    • 정적 --> 컴파일 타임에 결정

Example) RPG 게임에서 무기 구현

#include <iostream>
using namespace std;

class Weapon {
   public:
    Weapon(int power) : power(power) {
        cout << "Weapon(int)" << endl;
    }

    void Use() {
        cout << "Weapon::Use()" << endl;
    }

   protected:
    int power;
};

class Sword : public Weapon {
   public:
    Sword(int power) : Weapon(power) {
        cout << "Sword(int)" << endl;
    }
    void Use() {
        cout << "Sword::Use()" << endl;
        Swing();
    }

   private:
    void Swing() {
        cout << "Swing sword" << endl;
    }
};

class Magic : public Weapon {
   public:
    Magic(int power, int manaCost) : Weapon(power), manaCost(manaCost) {
        cout << "Magic(int, int)" << endl;
    }

    void Use() {
        cout << "Magic::Use()" << endl;
        Cast();
    }

   private:
    void Cast() {
        cout << "Cast magic." << endl;
    }
    int manaCost;
};

int main(void) {
    Sword mySword(10);
    Magic myMagic(15, 7);
    mySword.Use();
    myMagic.Use();
  • 자식 생성자가 호출되기 전에 반드시 부모 생성자가 호출된다

  • mySword.Use()의 경우 Sword::Use()가 호출된다

  • myMagic.Use()의 경우 Magic::Use()가 호출된다

  • 우리가 게임을 할 때 무기로 칼을 사용할 수도 있고, 마법 지팡이를 사용할 수도 있다.

        // 메인 함수 이어서
    Weapon *currentWeapon;

    currentWeapon = &mySword;
    currentWeapon->Use();
}
  • currentWeapon->Use()의 경우 Weapon::Use()가 호출된다

    • 정적 바인딩

가상 함수

  • 우리는 내가 들고있는 무기의 Use()를 호출하고 싶다.

    • 이를 위해서 virtual 키워드를 사용하기만 하면 된다
class Weapon {
   public:
    /* 생략 */

    virtual void Use() {
        cout << "Weapon::Use()" << endl;
    }

        /* 생략*/

};

int main(void) {

        /* 생략 */
        Weapon *currentWeapon;

    currentWeapon = &mySword;
    currentWeapon->Use();
}
  • currentWeapon->Use()에서 Sword의 Swing이 호출된다
currentWeapon = &myMagic;
currentWeapon->Use();
  • currentWeapon->Use()에서 myMagic의 myMagic이 호출 된다

컴파일러가 가상 함수를 처리하는 방식

  1. currentWeapon->Use()를 보고 부모 클래스의 Use() 함수를 살펴본다

  2. virtual로 선언되있는 것을 보고 가상 함수라는 것을 확인한다

  • 가상 함수란 이 함수가 실행이 될 수도 있고, 안될 수도 있다는 의미를 내포

    • 컴파일러는 컴파일 할 때 virtual 함수를 만나면, 런타임에 바인딩을 결정하도록 미룬다.

      • 프로그램을 만드는 시점에는 함수가 실행 될지 안될지 모르기 때문에 프로그램이 실행되는 시점에 결정하게끔 한다.
  1. 런타임 중에는 currentWeapon이 어떤 타입의 객체를 가리키고 있는지 알 수 있기 때문에, 가리키는 객체 타입에 해당하는 함수가 실행된다

참조) 두들낙서 C/C++ 강좌