1. 함수 바인딩 (Function binding)


함수 호출하는 코드에서 실제 호출할 함수를 결정하는 것을 함수 바인딩이라 한다.



L15 ~ 17 은 다 같은 객체 s의 멤버 함수지만 호출되는 함수는 다르다.


함수 바인딩에는 static binding과 dynamic binding이 있다.


Static binding

컴파일 시점에 함수를 결정한다. C++의 비 가상 함수


Dynamic binding

런타임 시점에 함수를 결정한다. C++의 가상함수, JAVA, objective-C 등의 다른 언어에서 쓰인다.




2. Static binding


Static binding은 멤버 함수를 컴파일 시간에 결정해야 하는데, 컴파일 시점에 항상 객체의 타입을 결정할 수는 없다.



L9에서 p는 사용자 입력에 따라 타입이 달라지기 때문에 p가 어떤 타입인지 컴파일러는 알 수 없다.


하지만 print 멤버가 가상함수가 아닌 경우는 static binding 때문에 컴파일 시간에 print 함수를 결정해야 한다.


이때 컴파일러는 p의 포인터 타입만 알고 있기 때문에, p의 타입을 보고 (person* 타입) person의 멤버 함수를 부르게 된다.

(p는 person*이기 때문에 p가 person의 파생 클래스여도 person의 멤버함수 print는 항상 있디)




3. Dynamic binding


Dynamic binding은 가상 함수를 런타임 시간에 결정하는데, 이를 위해 가상 함수 테이블 (virtual function table)을 따로 유지하고, 거기에 가상 함수의 함수 포인터를 보관한다.


다음 예를 통해서 가상함수 테이블의 크기를 유추해 볼 수 있다.



personWOvt는 가상함수가 없기 때문에 사이즈가 1이고 (0인 경우 sizeof가 들어간 다른 구문에 (나누기 같은 경우) 에러를 발생시킬 수 있어 최소 1을 리턴)


person은 가상함수가 있기 때문에 사이즈가 8이다. (32비트의 경우 4바이트씩 증가)


이 가상함수 테이블은 만일 파생클래스에서 가상함수를 오버라이딩 하는 경우, 컴파일러가 부모 클래스의 가상함수를 교체하게 된다.


가상함수의 단점

가상함수마다 메모리가 추가로 필요하다

함수 호출 시 가상함수 테이블을 참조한 후에 호출하여 오버헤드가 발생한다.

인라인 치환을 사용할 수 없다. (컴파일 시점에 치환을 결정할 수 없음)




4. RTTI (Run-Time Type Information)


가상함수 테이블에는 가상함수의 함수 포인터 외에 추가로 이 객체가 원래 어떤 타입인지를 가리키는 정보를 추가로 가지게 된다. 이것을 조사하는 것을 RTTI라고 부른다.


이 타입 정보는 아래와 같이 사용할 수 있다.



1) const type_info reference type으로 받는다.

2) typeid(객체) 또는 typeid(student)로 조사한다.

3) #include <typeinfo>




5. Dynamic_cast


앞에서 나왔던 dynamic_cast가 이 RTTI를 이용한다. 


런타임에 타입을 조사하여 변환 가능하면 포인터를 리턴하고, 

그렇지 않다면 (상속 관계가 없다면) 0을 리턴한다.



student 는 person의 자식 클래스이므로 정상적으로 캐스팅 되지만,

cat은 person의 자식 클래스가 아니기 때문에 캐스팅 되지 않고 nullptr가 리턴된다.

(만일 static_cast를 썼다면, cat도 강제로 캐스팅 되어버린다)

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

템플릿 주의할 점  (0) 2018.12.24
템플릿 (Template)  (0) 2018.11.04
가상 함수 (Virtual Function)  (0) 2018.10.23
상속 (Inheritance)  (0) 2018.10.22
연산자 재정의 (Operator overloading)  (0) 2018.07.01

+ Recent posts