我创建了自定义随机数生成器,并将其全局函数放在一个名为SamRandom.h的文件中。该文件如下所示:
#ifndef _SAM_RANDOM_H
#define _SAM_RANDOM_H
#include <cstdlib>
#include <ctime>
void InitialiseRandomSeed()
{
//...
}
//...
#endif
我在一个非常复杂的面向对象程序中工作,该程序包含许多不同的组件。每次我添加一个与此文件无关的文件时,都会收到以下冲突消息:
LaserBase.obj:-1: error: LNK2005: "void __cdecl InitialiseRandomSeed(void)" (?InitialiseRandomSeed@@YAXXZ) already defined in main.obj
error: LNK1169: one or more multiply defined symbols found
在MSVC和MinGW上,我得到:
In function `Z20InitialiseRandomSeedv':
SamRandom.h:8: multiple definition of `InitialiseRandomSeed()'
error: first defined here
:-1: error: collect2: ld returned 1 exit status
为什么会这样?我认为预处理器指令应该可以防止这个问题发生......这真的让我发疯了!!!
P.S。:问题与功能名称无关。
感谢您的任何努力
答案 0 :(得分:2)
当您将文件包含在.cpp文件中时,预处理器会直接将其复制到该文件中。因此,当您编译该.cpp文件时,目标文件(即使您无法识别,编译器始终会执行的步骤)将包含该函数。如果将其包含在多个.cpp文件中,则每个目标文件都将包含该函数。当链接器尝试将所有目标文件链接到可执行文件时,它会找到函数x-times并给出该错误。 “找到一个或多个多重定义的符号”表示它不止一次发现了你的一个函数(或变量)并且不知道如何处理它。
为了避免这种情况,你应该只设置你的签名。例如
//whatever.h
#ifndef _SAM_RANDOM_H
#define _SAM_RANDOM_H
void InitialiseRandomSeed();
#endif
在头文件中并将实现放入单独的.cpp文件中:
//whatever.cpp
#include "whatever.h"
#include <cstdlib>
#include <ctime>
void InitialiseRandomSeed()
{
//...
}
答案 1 :(得分:2)
标头保护确保在单个编译单元(.cpp文件)中未多次定义该函数。但是,它们不会阻止在多个编译单元中一次定义该函数。这是因为头包含函数的定义,因此包含头的每个.cpp都有自己的函数定义。
您可以将定义移动到SamRandom.cpp,而不是像这样在标题中声明函数:
void InitialiseRandomSeed();
或者,您可以指定该函数是内联函数,这将使多个定义可以接受:
inline void InitialiseRandomSeed()
{
//...
}
假设该函数不是性能关键且不经常调用,我会采用前一种方法。这使标题更易读,并且(通常)减少了编译时间。
答案 2 :(得分:1)
您可以将定义分隔为.cpp文件,只需在标题中声明该函数。