我在使用名称空间时遇到了一个lnk2005错误。我想不出如何解决这个错误。下面是错误:
1>Source.obj : error LNK2005: "int Chart::Bars::d" (?d@Bars@Chart@@3HA) already defined in Chart.obj
1>Source.obj : error LNK2005: "class foo Chart::l" (?l@Chart@@3Vfoo@@A) already defined in Chart.obj
1>Source.obj : error LNK2005: "int Chart::t" (?t@Chart@@3HA) already defined in Chart.obj
1>C:UsersbnmdevexamplesplaynmspcaDebugnmspca.exe : fatal error LNK1169: one or more multiply defined symbols found
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:00.49
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
代码如下:
Chart.h
#pragma once
#include "foo.h"
namespace Chart
{
int t;
foo l;
namespace Bars
{
int d;
}
}
foo。
#pragma once
class foo
{
public:
int ss;
char* h;
};
Chart.cpp
#include "Chart.h"
using namespace Chart;
int main ()
{
l.h = "g";
}
Source.cpp
#include "Chart.h"
using namespace Chart;
int test()
{
l.ss = 0;
return l.ss;
}
当从Source.cpp中删除#include "Chart.h"时,问题就解决了。但是,Source.cpp需要#include "Chart.h"来定义命名空间。
如何正确表达在Chart.cpp和Source.cpp中都需要"namespace Chart",以使一切都能编译?
如果您在头文件中定义了任何对象,并将该头文件包含在多个翻译单元中,那么这些对象现在将被多次定义。这就是你的问题所在。t
, l
和d
的声明引入了对象,并且您已经在头文件中这样做了。
支持名称空间作用域变量的正确方法是在头文件中将它们声明为extern
。这使得它们只是声明而不是定义。然后,在单个实现文件中定义它们。
修改Chart.h
为:
#pragma once
#include "foo.h"
namespace Chart
{
extern int t;
extern foo l;
namespace Bars
{
extern int d;
}
}
然后在一个实现文件中,也许是Chart.cpp
,做:
int Chart::t;
foo Chart::t;
int Chart::Bars::d;
在包含Chart.h的任何地方,都有效地将变量t、l和d放入这些对象中。将它们声明为extern,然后在Chart.cpp
我遇到了完全相同的问题,我找到了一个解决方法。
chart.h就变成:
#pragma once
#include "foo.h"
class Chart{
static int t;
static foo l;
class Bars
{
static int d;
};
};
并在chart.cpp
中定义变量int Chart::t;
foo Chart::l;
int Chart::Bars::d;
很丑,我知道,但至少在需要使用变量的地方语法是一样的。
这种方法只创建一个.obj文件,其中包含防止多个定义错误的变量。
我还没有尝试过是否可以在命名空间上声明一个静态变量来解决这个问题。
注:这个解决方案在msvc上产生了一些奇怪的错误,好像每次包含它时,代码的各个部分都会引用不同的变量
在我自己的程序上测试了static-inside-namespace,它似乎有效。
Example.h:
namespace sdl{
static SDL_Surface* screen;
static int xres = 640;
static int yres = 480;
static int bpp = 32;
static int flags = SDL_ASYNCBLIT;
};