동적 바인딩 (virtual 키워드를 사용할 경우 vtable을 통해 구현됨)

ㄴ 런타임에 어떤 함수가 호출될지를 정함

 

정적 바인딩 (virtual 키워드 쓰지 않은 함수)

ㄴ 컴파일 타임에 어떤 함수가 호출될지를 정함

 

override 키워드

C++11 에서부터 파생 클래스에서 기반 클래스의 가상 함수를 오버라이드 하는 경우 override 키워드를 통해 명시적으로 나타낼 수 있음

 // 기반 클래스
 virtual void what() { std::cout << s << std::endl; }
 
 // 파생 클래스
 void what() override { std::cout << s << std::endl; }

 

virtual 소멸자

// 부모 클래스의 소멸자에 virtual을 붙이지 않는 경우

// parent 생성자 - child 생성자 - child 소멸자 - parent 소멸자 순으로 정상적으로 호출된다.
Child *c = new Child();
delete c;

// parent 생성자 - child 생성자 - parent 소멸자 순으로 호출된다.
// 자식 클래스의 소멸자가 호출되지 않는다.
Parent *p = new Child();
delete p;

소멸자가 호출되지 않는 문제는 Child 객체의 생성자에서 멤버 변수들을 위해 메모리를 동적 할당했을 경우 메모리 누수로 이어질 수 있다.

 

가상 함수의 구현 원리 (vtable), 가상 함수의 오버헤드

가상 함수가 하나라도 존재하는 클래스의 객체의 가장 윗 부분에는 vtable의 주소값이 저장되어 있다. (x64 에서는 8byte)

포인터가 아닌 실제로 가리키고 있는 객체(클래스)의 vtable을 참조한다. 

자식 클래스의 vtable은 부모 클래스의 vtable값이 그대로 복사되며, 오버라이딩 된 함수만 주소가 새로 업데이트된다.

vtable에는 virtual로 선언된 가상 함수만 저장된다.

vtable은 클래스 단위로 만들어진다. (만들어지는 객체의 개수와 관련이 없다)

 

일반 함수를 호출하는 경우 함수는 바로 호출되지만

가상 함수를 호출하는 경우 가상 함수 테이블을 한번 거쳐서 함수를 호출하기 때문에 시간이 더 오래 걸린다. (오버헤드)

 

순수 가상함수와 추상 클래스

순수 가상함수를 한 개 이상 가진 클래스를 추상 클래스라고 한다.

class Animal {
 public:
  Animal() {}
  virtual ~Animal() {}
  // 순수 가상 함수 // 반드시 오버라이딩 되어야 하는 함수
  virtual void speak() = 0;
};

 

참조:

https://modoocode.com/210

'C++' 카테고리의 다른 글

C++ Callable  (0) 2022.08.26
C++ RAII와 스마트포인터  (0) 2022.08.26
C++ 템플릿, 함수 객체(Functor)  (0) 2022.08.25
C++ r-value 참조와 move, 이동 생성자  (0) 2022.08.25
C++ 문자열 처리  (0) 2022.08.24

+ Recent posts