我有一个MFC应用程序AVT_testapp,并且在头文件(AVT_testappDlg.h)中我试图在所有函数,类等之外创建一个变量,以使其成为全局变量。每当我尝试这样做时(比如我尝试int x = 7
),我都会收到错误:
1>AVT_testappDlg.obj : error LNK2005: "int x" (?x@@3HA) already defined in
AVT_testapp.obj
1>..\..\bin\x64\Debug\AVT_testapp.exe : fatal error LNK1169: one or more
multiply defined symbols found
我在google上发现的所有内容都说“只需添加标题保护”。 AVT_testappDlg有6个#include,并且每个都有标题保护。
创建全局变量时还有什么可能导致这些错误?
编辑:这是我的头文件的开头,
#pragma once
#include "../../src/CoreUtils/nierr.h"
#include "..\..\src\CoreUtils\StringHelpers.h" //includes windows.h
#include "afxwin.h"
#include "afxcmn.h"
#include "IFrameObserver.h"
#include "c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\GdiPlusHeaders.h"
//#include <fstream>
//#include <windows.h>
int x = 7;
using namespace AVT::VmbAPI;
//////////////////////////////////////////////////////////////////////////
////////// MyObserver class ///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
class MyObserver : public IFrameObserver
{
private:
MyObserver( MyObserver& );
MyObserver& operator=( const MyObserver& );
public:
VmbUchar_t* imageData;
//...
//...
//...
//...
//that's the end of the relevant stuff
答案 0 :(得分:10)
您无法在标头的命名空间级别定义变量。一般来说,最好不要有全局变量,但如果需要,你应该只在标题中提供声明,并在单个.cpp中提供定义:
//header
extern int i;
//cpp
int i;
您的代码问题与标题保护无关。标题保护确保在每个翻译单元中仅解析标题一次。缺少标头保护会导致编译器错误,编译器会在预处理后看到(例如一个类)在同一转换单元中多次定义的错误。在您的情况下,错误是链接器错误 LNK2005 ,这意味着在多个翻译单元中定义了相同的符号(在您的情况下,在每个翻译单元中包含带定义的标题)。
答案 1 :(得分:5)
如果全局变量不是const
(*),则不能将其放在头文件中并将其包含在多个翻译单元(即.cpp
文件)中。否则,您将在程序中找到同一符号的多个定义,违反 ODR (一个定义规则,请参阅C ++ 11标准的第3.2段) ,连接器会抱怨这一点。
您应该使用共享标头中的extern
修饰符仅提供变量的声明:
extern int var;
然后,在一个 .cpp
文件中,您可以为其提供定义:
int var;
(*)const
全局变量默认具有内部链接,因此每个翻译单元最终都会拥有它的私有副本,并且不会出现多重定义。
答案 2 :(得分:1)
如果你坚持让全局变量至少把它放在命名空间中以避免与其他模块冲突
namespace globals
{
extern int x;
}
然后在.cpp文件中定义它。
int globals::x = 0;
它也更清楚地表明它是一个全局变量。