外部声明变量的定义适用于一个函数,但不适用于另一个函数

Definition of externally declared variable works in one function, but not another

本文关键字:适用于 函数 一个 另一个 不适用 变量 声明 定义 外部      更新时间:2023-10-16

我正在编写一个基于对话框的小型Win32应用程序。单击菜单按钮时,我需要创建并显示第二个对话框。我在一个外部头文件-wedge.h 中声明了HWND

楔形。h

#pragma once
#include <Windows.h>
#include "utilities.h"
extern HWND wedgedialog;
INT_PTR CALLBACK WedgeProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);

当我尝试在WinMain函数中定义wedgedialog并在DialogProc函数中使用该变量时,我会从链接器中得到一个"未解析的外部符号"错误。当我在DialogProc中定义并使用wedgedialog时,一切都很好。为什么定义在一个函数中有效,而在另一个函数却无效?请记住,我的WinMain和DialogProc函数在同一个文件中。

main.cpp

INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE h0, LPTSTR lpCmdLine, int nCmdShow)
{
HWND hDlg;
MSG msg;
BOOL ret;
InitCommonControls();
hDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(MAIN), 0, DialogProc, 0);

HWND wedgedialog = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(WEDGE), hDlg, WedgeProc);

ShowWindow(hDlg, nCmdShow);
HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1));
SetMenu(hDlg, menu);
while ((ret = GetMessage(&msg, 0, 0, 0)) != 0) {
    if (ret == -1)
        return -1;
    if (!IsDialogMessage(hDlg, &msg)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}
return 0;
}
INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
    DestroyWindow(hDlg);
    return TRUE;
    break;
case WM_DESTROY:
    PostQuitMessage(0);
    return TRUE;
    break;
case WM_COMMAND:
    switch (LOWORD(wParam))
    {
    case ID_EDIT_WEDGESETTINGS:
        ShowWindow(wedgedialog, SW_SHOW);
        break;
    }
    return TRUE;
    break;
}
return FALSE;
}

您并没有真正定义全局变量。您在_tWinMain函数中声明了一个名为wedgedialog的HWND类型的局部变量。局部变量不会因为有外部声明而自动升级为全局变量。extern声明确实告诉编译器某个地方有一个全局变量,这就是为什么DialogProc中的代码进行编译,但实际上没有可链接的全局变量。

为了实现这一点,您需要在任何函数之外声明一个全局变量,如下所示:

HWND wedgedialog = NULL;

然后在主函数中,使用CreateDialog调用删除行开头的HWND说明符,这样您只需分配给全局,而不是声明本地。

如果需要,可以将extern声明保留在头中,但除非在其他函数中使用该全局声明,否则并不真正需要它。尽管可以说有比使用global更好的设计。您可以用静态成员声明一个类,至少可以避免全局命名空间。或者您可以有一个带有静态函数的类来返回一个singleton对象。

"extern HWND wedgedialog;"实际上并没有分配变量。它只是告诉编译器变量将被分配到另一个文件中,并将在链接过程中解析。在你的另一个文件中,需要有:

"HWND楔形对话框;"

实际分配内存中的变量。