Especificação de otimização do compilador para um projeto da ATL

Por padrão, o Assistente de Controle de ATL gera novas classes com a macro ATL_NO_VTABLE, da seguinte maneira:

class ATL_NO_VTABLE CProjName
{
...
};

A ATL então define _ATL_NO_VTABLE da seguinte maneira:

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

Se você não definir _ATL_DISABLE_NO_VTABLE, a macro ATL_NO_VTABLE será expandida para declspec(novtable). Usar declspec(novtable) em uma declaração de classe impede que o ponteiro vtable seja inicializado no construtor e no destruidor da classe. Quando você cria seu projeto, o vinculador elimina a vtable e todas as funções para as quais a vtable aponta.

Você deve usar ATL_NO_VTABLE e, consequentemente declspec(novtable), apenas com classes base que não podem ser criadas diretamente. Você não deve usar declspec(novtable) com a classe mais derivada em seu projeto, pois essa classe (geralmente CComObject, CComAggObject ou CComPolyObject) inicializa o ponteiro vtable para seu projeto.

Você não deve chamar funções virtuais do construtor de qualquer objeto que use declspec(novtable). Você deve mover essas chamadas para o método FinalConstruct.

Se você não tiver certeza se deve usar o modificador declspec(novtable), poderá remover a macro ATL_NO_VTABLE de qualquer definição de classe ou desabilitá-la globalmente especificando

#define _ATL_DISABLE_NO_VTABLE

em pch.h (stdafx.h no Visual Studio 2017 e anterior), antes de todos os outros arquivos de cabeçalho ATL serem incluídos.

Confira também

Assistente de Projeto da ATL
Tipos de projeto do C++ no Visual Studio
Programando com código de tempo de execução C e da ATL
Princípios básicos de objetos COM da ATL
novtable
Configurações de projeto padrão da ATL