관리 메뉴

有希

C++/바인딩(Binding) 본문

프로그래밍/C++

C++/바인딩(Binding)

有希. 2022. 1. 28. 16:49

바인딩

함수 호출할 때 어떤 주소에 있는 함수를 호출해야 하는지 컴파일 시 이어주는 단계.

일반함수는 정적 바인딩을 사용한다. -> 컴파일 시점에 결정

가상함수는 동적 바인딩을 사용한다. -> 실행 시점에 결정


부모가 한 번 virtual 선언을 하면 자식에 있는건 다 virtual이다.

Player가 있고 이를 상속받은 Knight가 있다고 할 때,

Player* player를 매개변수로 받는 PlayerMove 함수에 Knight를 넣는다. PlayerMove 함수에서는 player->Move() 함수를 실행시킨다.

Move를 virtual로 지정하지 않으면 Player의 Move가 실행되고

Move를 virtual로 지정하면 상속받은 Knight의 Move가 실행된다.

즉, 부모의 함수에 virtual을 지정하지 않으면 매개변수가 자식이어도 부모의 함수가 실행되고
     부모의 함수에 virtual을 지정한다면 매개변수로 넣어준 자식의 함수가 실행된다.


이렇게 동작하는 이유

분명 Player부모 타입으로 변환해서 매개변수로 넣었는데, Knight인 것을 어떻게 알고 상속받은 Knight의 함수를 호출해줄까?

가상함수 테이블이 만들어지기 때문.(.vftable)

이 녀석도 주소값을 가지고 있는데, 32비트 64비트 시스템에 따라 4,8바이트 구분해서 들고 있다.
이 테이블에 가상함수들을 저장해놓고 해당 매개변수의 가상함수가 호출될 때 이 테이블에서 찾아서 실행해준다. 결국에는, Knight를 Player로 변환해서 넣었으나 함수 내용까지 다 덮어쓴 것은 아니므로 Knight의 함수 주소로 가서 Knight의 함수를 실행시켜주었기 때문이다.

그러면, 가상함수 테이블은 누가 만드는가? 생성자가 만든다.

Knight가 생성될 때 모든 다른것들 이전에 나의 가상함수 테이블을 Player의 함수들이 아닌 나의 함수들로 덮어씌운다. (Player도 자기가 virtual이 있으니 자기 vftable에 자기 함수들 써 놓을것임)


결론

일반함수를 작성했다면 컴파일 시에  정적 바인딩을 사용하여 딱 정해주었으므로, 코드에서 실행시켰을때 무엇을 실행할지 딱 정해져 있다.

가상함수를 작성했다면 런타임 중에 객체가 생성되면서 vftable을 만들고 실행->테이블이동->함수로 이동하여 실행.

즉, 일반함수는 실행->함수로 이동하여 실행의 2단계라면
     가상함수는 실행->vftable을 본다->함수로 이동하여 실행의 3단계를 거친다.

'프로그래밍 > C++' 카테고리의 다른 글

C++/malloc(free) vs new(delete)  (0) 2022.01.28
C++/메모리 구조  (0) 2022.01.28
C++/순수 가상 함수  (0) 2022.01.28
C++/객체지향 3대 특징  (0) 2022.01.28
C++/문자열 관련 함수 4총사  (0) 2022.01.28