COM, ATL

ATL_NO_VTABLE

디버그정 2008. 8. 30. 21:26
Visual C++ 개념: 프로젝트 만들기 및 관리
ATL 프로젝트에 대한 컴파일러 최적화 지정

기본적으로 ATL 컨트롤 마법사는 ATL_NO_VTABLE 매크로를 사용하여 다음과 같이 새 클래스를 생성합니다.

class ATL_NO_VTABLE CProjName
{
   ...
};

그런 다음 ATL은 다음과 같이 _ATL_NO_VTABLE을 정의합니다.

#ifdef _ATL_DISABLE_NO_VTABLE
   #define ATL_NO_VTABLE
#else
   #define ATL_NO_VTABLE __declspec(novtable)
#endif

_ATL_DISABLE_NO_VTABLE을 정의하지 않으면 ATL_NO_VTABLE 매크로가 declspec(novtable)으로 확장됩니다. 클래스 선언에서 declspec(novtable)을 사용하여 클래스 생성자와 소멸자에서 vtable 포인터가 초기화되지 않게 합니다. 프로젝트를 빌드할 때 링커는 vtable과 vtable이 가리키는 모든 함수를 제거합니다.

ATL_NO_VTABLE, 결과적으로 declspec(novtable)은 직접 만들 수 없는 기본 클래스와 함께 사용해야 합니다. declspec(novtable)를 프로젝트에서 가장 많이 파생되는 클래스와 함께 사용해서는 안 됩니다. 대개 CComObject, CComAggObject 또는 CComPolyObject인 이 클래스는 프로젝트의 vtable 포인터를 초기화하기 때문입니다.

declspec(novtable)을 사용하는 개체의 생성자에서 가상 함수를 호출해서는 안 됩니다. 그러한 함수 호출은 FinalConstruct 메서드로 이동해야 합니다.

declspec(novtable) 한정자를 사용해야 할지 여부가 확실하지 않은 경우에는 다른 모든 ATL 헤더 파일이 포함되기 전에, 모든 클래스 정의에서 ATL_NO_VTABLE 매크로를 제거하거나

#define _ATL_DISABLE_NO_VTABLE

ATL_NO_VTABLE 매크로를 전역적으로 비활성화하도록 stdafx.h에서 지정할 수 있습니다.

참고 항목

추상 클래스의 생성자에서 초기화된 가상 함수 테이블 포인터는 파생클래스(CComObject)의 생성자에 의해 다시 한번 덮어 씌여지게 되므로 필요없게 된다. 따라서 이 매크로가 지정되면 가상함수테이블과 가상함수를 없애고 가상함수테이블포인터를 적절하게 초기화 하게 된다.
클래스의 생성자에서 가상함수를 호출하지 않도록 해야 하는데 호출해야 할 필요가 있다면 FinalConstruct
()를 사용하면 된다. 이 멤버함수가 호출되는 때는 이미 COM 객체 클래스의 인스턴스가 생성되어 초기화된 상태이므로 안전하게 가상함수를 호출할 수 있게 된다.
사용여부를 알 수 없다면 ATL_NO_VTABLE을 삭제하던지 stdafx.h헤더파일에서 _ATL_DISABLE_NO_VTABLE 매크로를 사용해 이 속성을 사용하지 않도록 한다.