Я играл с пространствами имен, когда столкнулся с ошибкой 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:\Users\bnm\dev\examples\play\nmspca\Debug\nmspca.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.h
#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;
}
Когда #include «Chart.h» из Source.cpp удалено, проблемы исчезают. Однако для определения пространства имен для Source.cpp требуется #include «Chart.h».
Как правильно выразить эту «диаграмму пространства имен», необходимую как в Chart.cpp, так и в Source.cpp, чтобы все компилировалось?
Если вы определяете какие-либо объекты в заголовочном файле и включаете этот заголовочный файл в несколько единиц перевода, эти объекты теперь определяются несколько раз. Это проблема, с которой вы столкнулись. Декларации 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, как будто каждый раз, когда он включен, разделы кода ссылаются на разные переменные
Протестировал на моей собственной программе статическое внутреннее пространство имен, и это, кажется, работает.
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;
};