};
class D : public C {
public:
D(void) {}
// Определим функцию InitExtra
virtual void InitExtra(void) {
/* что-то содержательное */
}
};
// Фрагмент программы:
C *pc = new C; // Здесь компилятор выругается по поводу
// недопустимости создания абстрактного класса.
D *pd = new D; // А здесь компилятор все пропустит.
// Но! см. ниже…
При создании объекта класса D первым, как полагается, будет создан объект класса C. В его конструкторе будет вызван статический метод Init, который, в свою очередь, вызовет виртуальный InitExtra, и вылетит с ошибкой Pure virtual call или что-то вроде этого, поскольку в VMT класса C на месте InitExtra находится 0 (вернее – вызов обработчика аварийной ситуации), а VMT наследника еще не создан.
Геннадий Васильев
Это все на сегодня. До встречи!
Алекс Jenter jenter@rsdn.ru Duisburg, 2001. Публикуемые в рассылке материалы принадлежат сайту RSDN.
Программирование на Visual C++
Выпуск №54 от 11 ноября 2001 г.
Здравствуйте, уважаемые подписчики!
Я наконец разобрался с CHM-файлом архива рассылки, так что теперь там поиск должен работать нормально (правда, как и раньше, только для латиницы). Новый файл, в который я заодно добавил вышедшие за это время выпуски, можно скачать здесь.
Сегодня в выпуске – долгожданное продолжение руководства по WTL Александра Шаргина. К сожалению из-за большого объема статьи, которую даже пришлось разбить на две части, остальных рубрик сегодня не будет. Но статья того без сомнения стоит!
CТАТЬЯ
Использование WTL
Часть 2. Диалоги и контролы
Диалоги
Диалоговые окна широко используются в Windows-приложениях, начиная с момента выхода самой операционной системы Windows. Они очень удобны для организации диалога с пользователем (отсюда их название). Кроме того, в несложных приложениях часто удаётся построить на базе диалогов не только вспомогательные окна, но и главное окно приложения (такие приложения иногда называют "dialog-based"). В этом разделе мы рассмотрим классы WTL, предназначенные для работы с диалоговыми окнами.
Классы WTL для работы с диалогами
Классы WTL, относящиеся к диалоговым окнам, показаны на рисунке 1.
Рисунок 1. Диалоговые классы WTL
Обратите внимание, что все диалоговые классы порождаются от базового класса CWindowImplRoot<>, а не от класса CWindowImpl<>. Это сделано потому, что диалоги, в отличие от всех остальных окон, не используют оконную процедуру для обработки сообщений. Вместо этого используется диалоговая процедура, адрес которой задаётся при создании диалога. WTL предоставляет вам свою реализацию диалоговой процедуры в классе CDialogImplBaseT<>. Соответственно, все остальные классы диалогов WTL наследуют эту реализацию.
ПРИМЕЧАНИЕ
Все классы, показанные на рисунке 1, WTL унаследовала от библиотеки ATL. Они описаны в файле atlwin.h
Теперь изучим каждый класс более подробно.
Класс CDialogImplBaseT<>
Итак, класс CDialogImplBaseT<>содержит функциональность, необходимую всем без исключения диалоговым окнам. Это, в первую очередь, поддержка диалоговых процедур, а также пара вспомогательных функций. Обратите внимание, что в класс CDialogImplBaseT<>не встроен механизм создания диалога при помощи функций DialogBoxи CreateDialog. Дело в том, что не все диалоги нуждаются в этих функциях. Например, стандартные диалоги создаются при помощи специальных функций ( GetOpenFileName, ChooseColorи т. д.).
Диалоговые процедуры в классе CDialogImplBaseT<>реализованы более или менее аналогично оконным процедурам в классе CWindowImplBaseT<>.
template
LRESULT CALLBACK CDialogImplBaseT::StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
CDialogImplBaseT* pThis = (CDialogImplBaseT*)_Module.ExtractCreateWndData();
ATLASSERT(pThis != NULL);
pThis->m_hWnd = hWnd;
pThis->m_thunk.Init(pThis->GetDialogProc(), pThis);
WNDPROC pProc = (WNDPROC)&(pThis->m_thunk.thunk);
WNDPROC pOldProc = (WNDPROC)::SetWindowLong(hWnd, DWL_DLGPROC, (LONG)pProc);
#ifdef _DEBUG
// check if somebody has subclassed us already since we discard it
if (pOldProc != StartDialogProc)
ATLTRACE2(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n"));
#else
pOldProc; // avoid unused warning
#endif
return pProc(hWnd, uMsg, wParam, lParam);
}
template LRESULT CALLBACK CDialogImplBaseT::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
CDialogImplBaseT* pThis = (CDialogImplBaseT*)hWnd;
Читать дальше