이 내용 역시 면접 당시의 질문에서 버벅거린 사항들. 아...C++을 맞이한지 벌써 5년째 접어드는데, 이런 기본으로 아직까지도 버벅거리는 것을 보면, 거참...

virtual 키워드에 대해서
  • 다형성(polymorphism)이란?
    한 개의 기반 클래스(Base Class)에 대한 포인터나 레퍼런스를 통해, 한 개 이상의 파생(Derived) 타입을 조작할 수 있는 능력


  • 소멸자가 아닌 가상 소멸자(virtual destructor)를 사용하는 이유는?
    : 기반 클래스 인스턴스의 포인터나 레퍼런스로 파생 클래스의 인스턴스를 소멸하기 위해서. (기반 클래스 인스턴스의 포인터나 레퍼런스를 통해 파생 클래스 인스턴스를 파괴할 경우, 기반 클래스의 소멸자가 가상 소멸자가 아니라면, 파생 클래스의 소멸자를 호출할 방법이 없다. 결국, 파생 클래스 인스턴스는 완전히 파괴되지 않는다.)


  • 일반 멤버 함수와 가상 멤버 함수와의 차이는?
    : 일반 멤버 함수의 경우, 컴파일 타임에 그 멤버 함수가 담긴 클래스가 결정되지만(정적 바인딩), 가상 멤버 함수는 런 타임에 결정된다(동적 바인딩; 기반 클래스 인스턴스에 의해서 호출되기 때문에, 어떤 파생 타입의 멤버 함수가 호출될지를 컴파일 타임에 알 수가 없다).

  • virtual 키워드 또한 상속된다. : 기반 클래스의 멤버 함수가 가상 함수이면, 그 멤버 함수를 오버라이딩한 모든 파생 타입의 멤버 함수는 가상 함수가 되더라..설사 virtual 키워드가 붙지 않아도..


  • virtual 메카니즘이 재대로 동작하지 않는 경우
    (1) 기반 클래스의 생성자와 소멸자 안에서(그 안에서 가상 함수를 호출해도 파생 타입의 가상 함수가 호출되지 않고 기반 클래스의 멤버 함수가 호출된다)
    (2) 기반 클래스의 포인터나 레퍼런스가 아닌 기반 클래스의 객체를 사용한 경우(포인터나 레퍼런스는 파생 타입의 크기에 맞는 객체를 가리키지만, 객체는 단지 기반 클래스에 맞는 크기의 메모리만을 갖기 때문에).

  • 가상 함수를 갖는 각 클래스마다, 가상 멤버 함수 주소 목록이 담긴 가상 함수 테이블(vtbl; virtual function table)이 내부적으로 생성되고, 각 클래스의 인스턴스는 이 테이블을 가리키는 (숨겨진) 포인터 변수(vptr) 를 하나씩 갖는다. 그래서 그 포인터 변수 크기만큼 인스턴스의 크기는 커진다. 또한 가상 함수 호출은 이 테이블을 통해서 이루어지기 때문에, 필연적으로 일반 멤버함수보다 느려질 수밖에 없더라..(이같은 오버해드 땜시 MFC에서는 메시지 맵 메카니즘을 이용해서 다형성을 구현하더라..) - 그런데, 가상 함수 테이블은 어디에 생성되는지는 몰겠다...암만 찾아봐도 안나온다...으흐..

참고 자료: Essential C++(Stan Lippman저, 인포북), C++ Primer(Stan Lippman저, Addison Wesley), Microsoft Visual C++ Object Oriented Programming(삼양사), C++ Primer Plus(Stephen Prata, Sams), 이해석이란 분이 DEVPIA에 올린 가상 함수에 대한 짧은 강의
Posted by 어쨌건간에
TAG ,