C++ 与常量char*[]声明关联的重复符号错误
当我尝试用g++4.2.1进行编译时,我希望能够帮助诊断我收到的重复符号错误的来源 具体错误是C++ 与常量char*[]声明关联的重复符号错误,c++,linker,C++,Linker,当我尝试用g++4.2.1进行编译时,我希望能够帮助诊断我收到的重复符号错误的来源 具体错误是 ld: duplicate symbol _SOCIODEM_FILENAMES in /var/folders/c+/c+eq1Qz1Feye7vxs5mQOUE+++TI/-Tmp-//ccP3yVgF.o and /var/folders/c+/c+eq1Qz1Feye7vxs5mQOUE+++TI/-Tmp-//cc1NqtRL.o collect2: ld returned 1 exit
ld: duplicate symbol _SOCIODEM_FILENAMES in /var/folders/c+/c+eq1Qz1Feye7vxs5mQOUE+++TI/-Tmp-//ccP3yVgF.o and /var/folders/c+/c+eq1Qz1Feye7vxs5mQOUE+++TI/-Tmp-//cc1NqtRL.o
collect2: ld returned 1 exit status
仅当我将此声明包含在名为Parameters.h的文件中时,才会发生错误:
// Parameters.h
#ifndef PARAMETERS_H
#define PARAMETERS_H
// ...[code snipped]...
const int NUM_SOCIODEM_FILES = 5;
const char * SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = { "LSPAN_PDF.txt",
"FLEDGE_PDF.txt",
"PAIR_PDF.txt",
"BIRTH_AGE_PDF.txt",
"SPLIT_PDF.txt" };
// ...[code snipped]...
#endif
我已经搜索了所有文件,这是唯一声明socialdem\u文件名的地方。当我注释掉声明时,“复制符号”错误消失了
我不熟悉链接器错误(如果是这样的话),希望您能帮助我解决这个问题。我所有的头文件都有#ifndef…#define…#endif
包装器。我的编译命令是
g++ -o a.out -I /Applications/boost_1_42_0/ Host.cpp Simulation.cpp main.cpp Rdraws.cpp
提前谢谢
解决方案摘要
我现在在参数中有了。h:
const char * const SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = { "LSPAN_PDF.txt",
"FLEDGE_PDF.txt",
"PAIR_PDF.txt",
"BIRTH_AGE_PDF.txt",
"SPLIT_PDF.txt" };
Parameters.h中的所有其他定义和声明保持不变。Andrey和其他评论者总结了一种使用extern
的替代方法,这对我来说是过分的。头保护(\ifndef..\endif
包装器)只是防止您在单个源文件中多次包含相同的头。您仍然可以有多个包含该头的源文件,每个源文件将分别声明该符号。由于它们都具有相同的名称,因此将这些源链接在一起将导致符号名称冲突。您可能希望在源文件而不是头文件中声明符号问题是您正在头文件中放置定义。如果您将该文件包含在多个编译单元(.cpp文件)中,则实际上您将创建多个定义,并且在链接时您将收到该错误
您需要将这两个定义都放在.cpp文件中,并且只在头文件中放一个声明:
extern const int NUM_SOCIODEM_FILES;
extern const char * SOCIODEM_FILENAMES[];
很可能,您正在将此文件包含在多个源文件中。问题在于,每次包含都会导致名为socialdem\u FILENAMES
的变量的单独定义。包括防护装置对此没有帮助。在单个编译单元中包含多个声明;它们不会阻止跨多个编译单元的多个定义
您需要做的是在头文件中将这些变量声明为extern
,然后在一个源文件中定义它们。e、 g
// Parameters.h
#ifndef PARAMETERS_H
#define PARAMETERS_H
// ...[code snipped]...
extern const int NUM_SOCIODEM_FILES;
extern const char * SOCIODEM_FILENAMES[];
// ...[code snipped]...
#endif
然后:
// Parameters.cpp (or some other source file)
const int NUM_SOCIODEM_FILES = 5;
const char * SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = { "LSPAN_PDF.txt",
"FLEDGE_PDF.txt",
"PAIR_PDF.txt",
"BIRTH_AGE_PDF.txt",
"SPLIT_PDF.txt" };
对于int
您可以不这样做,因为它是一个常量整数,因此编译器可以将其视为编译时常量,它甚至永远不会出现在编译后的代码中。但是,char*
不能这样处理,因此必须只有一个定义(在C++中称为“一个定义规则”)。正如其他人所建议的,一种方法是将NUM\u SOCIODEM\u文件
和SOCIODEM\u文件名
声明为extern
,并在外部文件中定义一次。另一种方法是将它们声明为静态
——这会导致它们在包含标头的每个对象文件中重复,但不会创建错误,因为该定义是该对象文件的专用定义。您选择哪个选项完全取决于您自己的喜好。由于某些原因,迄今为止,没有一个答案能够解释整数NUM\u socialdem\u文件
object和数组socialdem\u文件名
object之间的差异。后者触发链接器错误的原因已经解释过了:因为您将头文件包含到多个实现文件中。然而,前者链接没有任何问题(因为NUM\u socialdem\u文件声明确实没有问题)。为什么?
原因是您的NUM\u socialdem\u FILES
对象被声明为const
。在C++中,const对象默认有内部链接,这意味着即使在多个实现文件中定义它们也不会引起链接问题。换句话说,在C++中,你的<代码> NothSooCoDeMyFrase相当于
static const int NUM_SOCIODEM_FILES = 5; /* internal linkage */
这就是为什么它不会导致任何链接问题
同时,您的socialdem_文件名
并没有声明为常量,这就是它默认获得外部链接并最终导致链接器错误的原因。但是,如果您将您的socialdem\u文件名也声明为const
,问题就会消失
const char * const SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = {
...
注意额外的const
在声明中的位置。如果您只是添加额外的const
,而其他内容保持不变(即在头文件中保留定义Ifsocialdem_FILENAMES
),则即使您将头文件包含到多个翻译单元中,链接器也不会报告错误
不过,这不是一种推荐的方法,因为这样您将提供SOCIODEM_文件名
内部链接,并最终在每个翻译单元中提供SOCIODEM_文件名
数组的独立副本-这可能很好,但意义不大。因此,对于数组,通常最好使用其他答案中推荐的extern
方法
但是,请注意,您通常不应该对NUM\u socialdem\u文件执行此操作
声明!!!它很好,因为它是在头文件中定义的。除非您试图做一些不寻常的事情,否则标量常量通常应该在头文件中用初始值设定项定义——这样,它们可以在所有翻译单元中被视为编译时常量,这是一件非常有价值的事情。因此,请注意一些其他答案中提出的奇怪建议,即将NUM\u socialdem\u文件的定义也移动到.cpp
文件中-这实际上毫无意义,而且是完全错误的做法。你所说的int和double参数“在编译的代码中从未显示”是什么意思?我的所有其他参数都是常量数字类型,并且似乎在我的