2013-03-10 1 views
1

Я следую учебник по MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/ff381400(v=vs.85).aspxPure Virtual Method Вызывается прекратить

Это показывает, как сделать класс для создания окон в WINAPI.

Я сделал то же самое, что и они, за исключением того, что я поместил код создания в конструктор.

При запуске он дает чистый виртуальный метод, называемый ошибкой, и завершает программу без объяснения причин.

template<typename T> 
class Form 
{ 
    public: 
     Form(std::string Title, std::string Class, /*All other params*/); 

    private: 
     static LRESULT __stdcall WindowProcedure(HWND Hwnd, UINT Msg, WPARAM wParam, LPARAM lParam); 

    protected: 
     HWND WindowHandle = nullptr; 
     virtual LRESULT HandleMessages(UINT Msg, WPARAM wParam, LPARAM lParam) = 0; 
}; 



template<typename T> 
Form<T>::Form(std::string Title, std::string Class, /*All Other Params*/) 
{ 
    WNDCLASSEX WndClass = {/*Filled in with other params*/}; 

    RegisterClassEx(&WndClass); 
    WindowHandle = CreateWindowEx(/*Other params*/, this); 
} 

template<typename T> 
LRESULT __stdcall Form<T>::WindowProcedure(HWND Hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) 
{ 
    T* Data = nullptr; 

    switch (Msg) 
    { 
     case WM_NCCREATE: 
     { 
      CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam; 
      Data = reinterpret_cast<T*>(pCreate->lpCreateParams); 
      SetWindowLongPtr(Hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(Data)); 
      break; 
     } 

     default: 
     { 
      Data = reinterpret_cast<T*>(GetWindowLongPtr(Hwnd, GWLP_USERDATA)); 
      return Data ? Data->HandleMessages(Msg, wParam, lParam) : DefWindowProc(Hwnd, Msg, wParam, lParam); 
     } 
    } 
    return 0; 
} 

Тогда мое главное окно:

class MainWindow : public Form<MainWindow> 
{ 
    public: 
     MainWindow(std::string Title, /*Other params*/); 
     LRESULT HandleMessages(UINT Msg, WPARAM wParam, LPARAM lParam); 

     HWND WindowHandle() {return Form::WindowHandle;} 
}; 

MainWindow::MainWindow(std::string Title, std::string Class, /*Other params*/) {} 

LRESULT MainWindow::HandleMessages(UINT Msg, WPARAM wParam, LPARAM lParam) 
{ 
    switch(Msg) 
    { 
     case WM_CREATE: 
     { 
     } 
     break; 

     case WM_DESTROY: 
      PostQuitMessage(0); 
      break; 

     default: 
      return DefWindowProc(WindowHandle(), Msg, wParam, lParam); 
    } 

    return 0; 
} 

Это все. Почему это дает мне эту ошибку и как я могу ее исправить?

ответ

1

Я сделал то же самое, что и они, за исключением того, что я поместил код создания в конструктор.

Вот почему. Вызов метода virtual из конструктора не делает то, что вы ожидаете, - если вы не ожидаете, что он вызовет метод из текущего класса в иерархии. Когда выполняется конструктор базового класса, объект еще не имеет производного типа. И если вы вызываете метод virtual, который является чистым в текущем классе из конструктора этого класса, вы получите эту ошибку.