코가손의 블로그

C++ 정적 바인딩 vs 동적 바인딩 본문

C++/문법

C++ 정적 바인딩 vs 동적 바인딩

Cogason 2021. 11. 11. 10:23

정적 바인딩

C++은 기본적으로 정적 바인딩으로 설정되어 있다.

정적 바인딩이란 상속 관계에 있는 클래스 사이에서 발생한다.

 

예를 들어

Animal이란 부모 클래스를 상속받은 Dog클래스가 있다고 생각해 보자.

Animal클래스 에는 Speak()라는 메소드가 있고

Dog클래스는 부모클래스를 오버라이딩 한 Speak()메소드 가 있다.

 

Dog의 객체를 생성하고 Speak()메소드를 호출할 때

Animal클래스의 메소드가 호출될지, 아니면 Dog클래스의 메소드가 호출될까

 

Java의 경우 오버라이딩 된 자식 메소드가 호출된다.

C++는 Dog인스턴스의 포인터에 맞게 호출된다.

Java의 경우를 동적 바인딩, C++는 정적 바인딩 이라고 한다.

 

'Dog인스턴스의 포인터에 맞게 호출'

Animal* dog1 = new Dog();    // Animal을 상속받은 Dog
Dog* dog2 = new Dog();

dog1.Speak();    // (Animal포인터)Animal의 Speak()호출, Java에서는 Dog의 Speak() 호출
dog2.Speak();    // (Dog포인터)Dog의 Speak() 호출, Java에서는 Dog의 Speak() 호출

dog1과 같은 Dog객체를 만들어도 Animal로 포인팅 한다면 타입이 Animal인 것만 포인팅 가능하다.

 

 

C++에서 Java처럼 자식 클래스의 메소드가 호출되려면 virtual 키워드를 붙이면 된다.

virtual을 사용하면 동적 바인딩을 하겠다는 의미이다.

동적 바인딩은 실행 중에 어떤 함수를 호출할 지 결정하기 때문에 정적 바인딩 보다 느리다.

실행 중에 어떤 함수를 호출할 지 결정하기 위해 가상 테이블이 생성된다.

 

컴파일 시에 virtual을 정의한 메소드에 한해 가상 테이블이 생성되는데 오브젝트를 생성할 때 해당 클래스의 가상 테이블 주소가 함께 저장된다.

ex) __vfptr, 0x00335ac2

 

가상 테이블을 활용하여 자식 오브젝트가 메소드를 호출할 때 Speak메소드(Dog) 호출할 것이고 부모(Animal)메소드 말고 자신의 메소드를 호출한다는 것으로 설정할 수 있다. 이 때 실행중에 자식 메소드로 Jump해서 가상테이블로 접근해서 메소드 호출하기 때문에 가상 테이블은 힙 영역에 생성된다.

 

클래스의 생성자에는 선처리 영역이 있는데 각 클래스의 가상 테이블은 이 부분에서 할당 된다.

class Dog : public Animal
{
public:
    /* 
    선처리 영역
    */
    void Speak()
    {
        cout << "(Dog)Bark" << endl;
    }
};

 

'C++ > 문법' 카테고리의 다른 글

C++ 초기화 리스트  (0) 2021.11.11
C++ 객체 생성  (0) 2021.11.11
C++ 깊은 복사 vs 얕은 복사  (0) 2021.11.11
C++ static, extern  (0) 2021.11.09
컴파일 과정  (0) 2021.11.09
Comments