Пространства имен и включает в себя генерировать ошибку ссылки

Я играл с пространствами имен, когда столкнулся с ошибкой 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, чтобы все компилировалось?

1

Решение

Если вы определяете какие-либо объекты в заголовочном файле и включаете этот заголовочный файл в несколько единиц перевода, эти объекты теперь определяются несколько раз. Это проблема, с которой вы столкнулись. Декларации 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;
4

Другие решения

Куда бы вы ни включали Chart.h, вы фактически помещаете переменные t, l и d в эти объекты. Объявите их как extern, затем определите их в Chart.cpp

1

У меня была точно такая же проблема, и я нашел рабочую силу.

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;

};
0
По вопросам рекламы [email protected]