提问者:小点点

为什么要在头文件中声明的变量中使用extern?[副本]


在Visual Studio编译中经常收到LNK2005错误之后,我深入研究了C++头文件,并意识到错误是我在头文件和main.cpp中两次声明了一个变量,我还发现有几个用户给出了如何使用外部类型variable_name的解决方案;在头文件中作为这个问题的解决方案,阅读答案,3个问题浮现在我的脑海中:

1-您真的需要使用extern在头文件中声明任何类型的变量吗?如果是的话,为什么不使用它来声明头文件中的类,例如?

第二-在头文件中使用extern是一个好的实践吗?或者有没有更好的东西可以使用,不会给我上面收到的错误?

从我读到的内容来看,使用extern需要在。cpp文件中重新声明变量,但是如果它已经在头文件中声明了,为什么我不能在。cpp中设置它的值呢?

PS:下面是我深入研究头文件并在这里生成这个问题的原因:

toast_notification.h:

#pragma once

bool dollar_value_was_changed;
bool toast_notification_was_created;

void show_toast_notification(), create_and_initialize_toast_notification(), set_toast_notification();
bool is_windows_10();

toast_notification.cpp:

#include "toast_notification.h"

#include <Windows.h>
#include <VersionHelpers.h>
#include <wintoast/wintoastlib.h>

void show_toast_notification()
{
    if (is_windows_10())
    {
        if (!toast_notification_was_created)
            create_and_initialize_toast_notification();
    }
}

bool is_windows_10()
{
    if (IsWindows10OrGreater())
        return true;
    else
    {
        MessageBox(NULL, L"Teste", L"Título da janela?", MB_OK);

        return false;
    }
}

void create_and_initialize_toast_notification()
{
    WinToastLib::WinToast::instance()->setAppName(L"Toast Dollar");
    WinToastLib::WinToast::instance()->setAppUserModelId(WinToastLib::WinToast::configureAUMI(L"Teste", L"Toast Dollar"));
    WinToastLib::WinToast::instance()->initialize();

    toast_notification_was_created = true;
}

void set_toast_notification()
{
    WinToastLib::WinToastTemplate toast_notification = WinToastLib::WinToastTemplate(WinToastLib::WinToastTemplate::Text02);
    toast_notification.setTextField(L"Teste", WinToastLib::WinToastTemplate::FirstLine);
}

main.cpp:

#include "toast_notification.h"

#include <iostream>

int main()
{
    std::cout << "Hello World!\n";
    
    show_toast_notification();

    system("pause");
}

不要太关注代码,我请您将注意力转向变量TOAST_NOTIFICATION_WAS_CREATED,在我的头脑中,由于它已经在头文件中声明,我可以将它设置在。cpp中,除此之外,变量DOLLAR_VALUE_WAS_CHANGED(未使用)也生成了使我提出这个问题的错误

错误:

1> toast_notification.obj: error LNK2005: "bool dollar_value_was_changed" (?dollar_value_was_changed @@ 3_NA) already defined in main.obj
1> toast_notification.obj: error LNK2005: "bool toast_notification_was_created" (?doast_notification_was_created @@ 3_NA) already defined in main.obj```

共1个答案

匿名用户

在C++中,命名空间范围内的变量声明是一个定义,除非它声明为externextern防止声明成为定义。在程序中只能定义一次变量(除非将其设置为内联)。由于标头通常包含在多个翻译单元中,因此您将得到多个定义。

注意:我不建议让变量内联内联“变量”定义主要用于ConstExpr对象。通常,我建议不要使用非const全局数据。