C ++: связывание внешних переменных из пространства имен - PullRequest
4 голосов
/ 18 ноября 2010

Я не могу ссылаться на внешнюю переменную из пространства имен, используя extern. Он работает из глобальной области видимости, но как только в него добавляется пространство имен, он не может установить связь.

Мой файл констант выглядит так:

StringConstants.cpp

#include "MyString.h"

MyString test1("string1");

MyString test2("string2");

Основная программа выглядит так:

main.cpp

#include <stdio.h>
#include "MyString.h"

extern MyString test1;

namespace {
    extern MyString test2;
}

int main(void) {
    printf("%s\n", test1.Str());
    printf("%s\n", test2.Str());
}

Я получаю похожие ошибки как в GCC, так и в Visual Studio:

gcc    main.o StringConstants.o   -o main
main.o:main.cpp:(.text+0x49): undefined reference to `(anonymous namespace)::test2'
collect2: ld returned 1 exit status

1>Linking...
1>main.obj : error LNK2001: unresolved external symbol "class MyString `anonymous namespace'::test2" (?test2@?A0x0df4aa01@@3VMyString@@A)
1>C:\p4\namespace_repro\namespace_repro2\Debug\namespace_repro2.exe : fatal error LNK1120: 1 unresolved externals

Я попытался определить ссылку на test2 (extern MyString ::test2), но он просто думает, что test2 является статическим членом MyString. Именованное пространство имен не ведет себя иначе, чем анонимное. По разным причинам мы не хотим удалять пространства имен или помещать внешние объекты вне пространств имен.

Вот другие файлы для полноты:

MyString.h

class MyString {
public:
   MyString(const char* str): mStr(str) {};
   const char* Str() const { return mStr; }
private:
   const char* mStr; 
};

Makefile

CC=gcc 
CFLAGS=-Wall

main: StringConstants.o main.o

Цели для этой системы состоят в том, чтобы все константы были определены в одном файле и чтобы они были разрешены во время ссылки, а не в заголовке. Казалось, что приведенный выше код будет работать, но, поскольку он отклонен двумя разными компоновщиками, мне кажется, что мое понимание C ++ недостаточно хорошее. Советы о том, как заставить это работать, кроме размещения внешних элементов вне пространств имен?

Ответы [ 2 ]

5 голосов
/ 18 ноября 2010

Что ...

namespace { 
    extern MyString test2; 
} 

... означает, что test2 должен существовать в анонимном пространстве имен, но это не так - он находится в глобальном пространстве имен.Вы солгали своему компилятору, поэтому он генерирует объект, который не будет ссылаться.Вам нужно сделать объявление extern из той же области имен, что и переменная.

НО, должен быть StringConstants.h, который должен включать main.cpp, чтобы модуль компиляции знал о строках безлюбые дальнейшие заявления.

4 голосов
/ 18 ноября 2010

$ 7.3.1 / 2 - «Каждое имя объявлено первым в пространстве имен является членом этого Пространство имен. "

Это означает, что имя test2 является частью анонимного пространства имен и должно быть определено в этом пространстве имен, если оно используется.

Это проблема не только анонимного пространства имен, но и любого пространства имен.

...