2013-11-29 3 views
1

Я пытаюсь написать систему обработки ошибок в C++, которая вызывает функцию обратного вызова всякий раз, когда возникает ошибка. Однако, когда я пытаюсь запустить проект, компоновщик всегда жалуется на неразрешенный внешний символ.C++ Callbacks - нерешенный внешний символ

GEWindow.h:

#include <Windows.h> 
#include <stdlib.h> 
#include <string.h> 
#include <tchar.h> 
#include <functional> 

#ifndef GE_WINDOW 
#define GE_WINDOW 

//class GEWindow; 

//typedef void(*GE_ERROR_CALLBACK)(HWND, UINT, LPCWSTR); 

#define GE_WINDOW_REGISTERATION_FAILED 1 
#define GE_WINDOW_CREATION_FAILED 2 
class GEWindow { 
public: 
    typedef std::function<void(GEWindow *, UINT, LPCWSTR)> GE_ERROR_CALLBACK; 

    static int geCreateWindow(GEWindow *window); 
    static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); 
    static inline void setErrorCallback(GE_ERROR_CALLBACK fun) { errCallback = fun; }; 

    inline HWND getHWnd() { return hWnd; }; 
    inline int getWidth() { return _width; }; 
    inline int getHeight() { return _height; }; 
    inline LPCWSTR getTitle() { return _title; }; 

    inline void setWidth(int width) { _width = width; }; 
    inline void setHeight(int height) { _height = height; }; 
    inline void setTitle(LPCWSTR title) { _title = title; }; 

private: 
    static GE_ERROR_CALLBACK errCallback; 

    HWND hWnd; 
    int _width = 400, _height = 400; 
    LPCWSTR _title; 
}; 

#endif 

GEWindow.cpp:

#include "GEWindow.h" 

int GEWindow::geCreateWindow(GEWindow *window) { 
    HINSTANCE hInstance = GetModuleHandle(NULL); 

    TCHAR szWindowClass[] = _T("GEWindow"); 
    WNDCLASSEX wcex; 

    wcex.cbSize = sizeof(WNDCLASSEX); 
    wcex.style = CS_HREDRAW | CS_VREDRAW; 
    wcex.lpfnWndProc = GEWindow::WndProc; 
    wcex.cbClsExtra = 0; 
    wcex.cbWndExtra = 0; 
    wcex.hInstance = hInstance; 
    wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); 
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 
    wcex.lpszMenuName = NULL; 
    wcex.lpszClassName = szWindowClass; 
    wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); 

    if (!RegisterClassEx(&wcex)) 
    { 
     //if (!errCallback) 
     // errCallback(window, GE_WINDOW_REGISTERATION_FAILED, _T("Failed to register the GE window")); 
     MessageBox(NULL, _T("Failed to register"), _T("Error"), NULL); 
     return NULL; 
    } 

    window->hWnd = CreateWindow(
     szWindowClass, 
     window->_title, 
     WS_OVERLAPPEDWINDOW, 
     CW_USEDEFAULT, CW_USEDEFAULT, 
     window->_width, window->_height, 
     NULL, 
     NULL, 
     hInstance, 
     NULL); 

    if (!window->hWnd) { 
     //if (!errCallback) 
     // errCallback(window, GE_WINDOW_CREATION_FAILED, _T("Failed to create the GE window")); 
     MessageBox(NULL, _T("Failed to create"), _T("Error"), NULL); 
     return NULL; 
    } 

    ShowWindow(window->hWnd, SW_SHOW); 
    UpdateWindow(window->hWnd); 

    MSG msg; 
    while (GetMessage(&msg, NULL, 0, 0)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

    return 1; 
} 

LRESULT CALLBACK GEWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { 
    switch (message) 
    { 
    case WM_PAINT: 
     break; 

    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 

    default: 
     return DefWindowProc(hWnd, message, wParam, lParam); 
     break; 
    } 

    return 0; 
} 

main.cpp:

#include "GEWindow.h" 

static void error_callback(GEWindow *window, UINT errorCode, LPCWSTR message) { 
    MessageBox(window->getHWnd(), message, _T("Error"), NULL); 
} 

int WINAPI WinMain(HINSTANCE hInstance, 
    HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, 
    int nCmdShow) { 
    GEWindow window; 
    window.setWidth(500); 
    window.setHeight(500); 
    window.setTitle(_T("lala lulu")); 
    /* 
    error LNK2001: unresolved external symbol "private: static class std::function<void __cdecl(class GEWindow *, unsigned int, wchar_t const *)> GEWindow::errCallback" ([email protected]@@[email protected]$$A^[email protected]@[email protected]@[email protected]@A) 
    */ 
    window.setErrorCallback(error_callback); 

    GEWindow::geCreateWindow(&window); 
} 
+0

Рассмотрите возможность использования std :: function для достижения такого же результата без использования противных статических методов. – Till

ответ

2

При использовании статических переменных-членов, вы только объявить их в класса, вам необходимо указать их также. Это определение должно быть сделано в исходном файле, например:

GEWindow::GE_ERROR_CALLBACK GEWindow::errCallback; 
0

статической силы GeWindows :: error_callback() исправит эту problem..I нашел его после нескольких дней от дней помощи «Tony The Lion "(кредит ...)

+0

Пожалуйста, подумайте над тем, чтобы добавить объяснение к вашему ответу. Ваш ответ идет ** против лучших практик **, изложенных в комментарии, ** не объясняйте **, почему это решит проблему, и имеет ** опечатку **, из-за которой она не решит проблему на некоторых системах. – grochmal

Смежные вопросы