C ++回调 - 未解析的外部符号

时间:2013-11-29 09:48:21

标签: c++ error-handling callback unresolved-external

我正在尝试用c ++编写一个错误处理系统,它会在错误上升时调用回调函数。但是,每当我尝试运行项目时,链接器总是会抱怨未解析的外部符号。

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" (?errCallback@GEWindow@@0V?$function@$$A^AXPAVGEWindow@@IPB_W@Z@std@@A)
    */
    window.setErrorCallback(error_callback);

    GEWindow::geCreateWindow(&window);
}

2 个答案:

答案 0 :(得分:2)

使用静态成员变量时,只需在类中声明它们,您还需要定义它们。该定义必须在源文件中完成,如下所示:

GEWindow::GE_ERROR_CALLBACK GEWindow::errCallback;

答案 1 :(得分:0)

static void GeWindows :: error_callback()将解决这个问题。我在几天之后在&#34; Tony The Lion&#34;的帮助下找到了它。 (信用...)