为什么删除const会给我链接器错误?

时间:2009-07-07 19:41:21

标签: c++ linker const

我有一个全局变量:

const std::string whiteSpaceBeforeLeadingCmntOption = "WhiteSpaceBeforeLeadingComment";

当我删除此变量声明中的const时,出现以下链接器错误:

error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > whiteSpaceBeforeLeadingCmntOption" (?whiteSpaceBeforeLeadingCmntOption@@3V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@A) already defined in REGISTER_TO_UNSRLZ.obj

这是一个.h文件,它包含在各个地方,但我有一个#ifndef带,以避免将它包含在几个地方。任何想法错误是什么?

5 个答案:

答案 0 :(得分:5)

当你在.h中有const时,这是有效的,因为const意味着静态,所以你可以在多个compilands中拥有相同的变量。

通过删除.h文件中定义的变量的const,您将在同一程序中创建具有相同标识符的多个实例。

如果你需要删除.h,你可以这样做:

extern std::string whiteSpaceBeforeLeadingCmntOption;

然后:

std::string whiteSpaceBeforeLeadingCmntOption = "";

在你的一个.cpp文件中。

答案 1 :(得分:5)

问题在于,通过在头文件中定义它,它将在包含该头文件的每个编译单元中实例化,从而为链接阶段多次定义。

您要做的是在.h:

中声明
extern std::string whiteSpaceBeforeLeadingCmntOption;

然后在 cpp中声明:

std::string whiteSpaceBeforeLeadingCmntOption = "WhiteSpaceBeforeLeadingComment";

答案 2 :(得分:3)

在C ++中,const对象的名称是它们出现的编译单元的本地名称,或者是#included in。

答案 3 :(得分:2)

#ifndef sentinel只会阻止每个FILE多次包含它。

答案 4 :(得分:1)

因为如果你的标题包含在几个cpp文件中,那么你有多个同一变量的定义(这里是全局的)。这是语言所禁止的。

您想要的是将声明和定义分开:

标题:

extern std::string whiteSpaceBeforeLeadingCmntOption; // declaration
// the 'extern' keyword is here to be sure the linker will look in all cpp for the definition of this variable

在一个cpp中:

std::string whiteSpaceBeforeLeadingCmntOption = "WhiteSpaceBeforeLeadingComment"; // definition

对于类静态变量也是如此。

但是如果对象是const,那么编译器将只生成const对象的一个​​定义并将其放在只读内存中的某个位置。您不必在巫婆编译单元中指定它。