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

标签 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);
}

最佳答案

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

GEWindow::GE_ERROR_CALLBACK GEWindow::errCallback;

关于C++ 回调 - 未解析的外部符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20282761/

相关文章:

c# - 使用NServiceBus非常简单的错误处理

python - NameError : name 'form' is not defined (Python3)

java - java中抛出异常重构

c# - 为什么在捕获到 Exception 时停止调用 Timer 回调?

c++ - 重载运算符 = 用于类型转换

python - 构建 Cython 模块时如何覆盖 -DNDEBUG 编译标志

c++ - 具有不同签名的绑定(bind)函数

python - 如何从装饰器中获取对实例方法的引用

c++ - 将文本文件解析为对象时的错误处理

c++ - 如何在没有循环的情况下将 bool 矩阵的每个元素设置为 false