2016-04-20 3 views
0

Я запускаю mingw-w64 на Windows 7 Pro 64-bit.Ошибки пространства имен C++

У меня возникают ошибки при попытке кода в пространстве имен, но он отлично работает без пространства имен. Код:

//foo.h 

#ifndef FOO_H 
#define FOO_H 

namespace joke { 

    extern "C" int fooStack[10]; 
    extern "C" int *fooPtr; 
    extern "C" void fooInit(); 
    extern "C" void fooPush(int iVar); 
    extern "C" int fooPop(); 

} 

#endif // FOO_H 

// foo.cpp 

#include "foo.h" 

using namespace joke; 

int fooStack[10]; 
int *fooPtr; 

void fooInit() { 
    fooPtr = &fooStack[0] + 9; 
} 

void fooPush(int iVar) { 
    *fooPtr = iVar; 
    fooPtr -= 1; 
} 

int fooPop() { 
    int oVar; 
    fooPtr += 1; 
    oVar = *fooPtr; 
} 

// bar.cpp 

#include <iostream> 
#include "foo.h" 

using namespace std; 
using namespace joke; 

int inVar = 0; 
int outVar = 0; 

void Report() { 
    int i; 
    cout << "Pointer: " << fooPtr << endl; 
    cout << "Stack:  "; 
    for (i = 0; i < 10; i++) { 
     cout << fooStack[i] << " "; 
    } 
    cout << endl; 
    cout << "inVar:  " << inVar << endl; 
    cout << "outVar: " << outVar << endl << endl; 
} 

int main() { 
    int i; 
    fooInit(); 
    cout << endl; 
    cout << "Initializing" << endl; 
    Report(); 
    for (i = 0; i < 8; i++) { 
     inVar = (i * 34) + 34; 
     cout << "set inVar" << endl; 
     Report(); 
     fooPush(inVar); 
     cout << "Push inVar" << endl; 
     Report(); 
    } 
    for (i = 0; i < 8; i++) { 
     outVar = fooPop(); 
     cout << "Pop outVar" << endl; 
     Report(); 
    } 
    return 0; 
} 

Makefile:

all: 

    g++ -S foo.cpp 

    g++ -S bar.cpp 

    g++ -c foo.s 

    g++ -c bar.s 

    g++ -o FB foo.o bar.o 

Как я уже сказал, все это прекрасно работает, если спецификации пространства имен удаляются или commented- вне. С характеристиками пространства имен в месте, результаты:

c:\work\gccWork\FooTest>make 
g++ -S foo.cpp 
foo.cpp: In function 'void fooInit()': 
foo.cpp:11:2: error: reference to 'fooPtr' is ambiguous 
    fooPtr = &fooStack[0] + 9; 
^
foo.cpp:8:6: note: candidates are: int* fooPtr 
    int *fooPtr; 
    ^
In file included from foo.cpp:3:0: 
foo.h:9:18: note:     int* joke::fooPtr 
    extern "C" int *fooPtr; 
       ^
foo.cpp:11:12: error: reference to 'fooStack' is ambiguous 
    fooPtr = &fooStack[0] + 9; 
      ^
foo.cpp:7:5: note: candidates are: int fooStack [10] 
int fooStack[10]; 
    ^
In file included from foo.cpp:3:0: 
foo.h:8:17: note:     int joke::fooStack [10] 
    extern "C" int fooStack[10]; 
       ^
foo.cpp: In function 'void fooPush(int)': 
foo.cpp:15:3: error: reference to 'fooPtr' is ambiguous 
    *fooPtr = iVar; 
^
foo.cpp:8:6: note: candidates are: int* fooPtr 
int *fooPtr; 
    ^
In file included from foo.cpp:3:0: 
foo.h:9:18: note:     int* joke::fooPtr 
    extern "C" int *fooPtr; 
       ^
foo.cpp:16:2: error: reference to 'fooPtr' is ambiguous 
    fooPtr -= 1; 
^
foo.cpp:8:6: note: candidates are: int* fooPtr 
int *fooPtr; 
    ^
In file included from foo.cpp:3:0: 
foo.h:9:18: note:     int* joke::fooPtr 
    extern "C" int *fooPtr; 
       ^
foo.cpp: In function 'int fooPop()': 
foo.cpp:21:2: error: reference to 'fooPtr' is ambiguous 
    fooPtr += 1; 
^
foo.cpp:8:6: note: candidates are: int* fooPtr 
int *fooPtr; 
    ^
In file included from foo.cpp:3:0: 
foo.h:9:18: note:     int* joke::fooPtr 
    extern "C" int *fooPtr; 
       ^
foo.cpp:22:10: error: reference to 'fooPtr' is ambiguous 
    oVar = *fooPtr; 
     ^
foo.cpp:8:6: note: candidates are: int* fooPtr 
int *fooPtr; 
    ^
In file included from foo.cpp:3:0: 
foo.h:9:18: note:     int* joke::fooPtr 
    extern "C" int *fooPtr; 
       ^
make: *** [all] Error 1 

Я просмотрел различные C++ учебников и литературы, а также несколько ссылок и форумов здесь на сайте. Я не вижу никаких проблем с синтаксисом.

Что мне не хватает?

+0

в '' foo.cpp'' вы пишете '' using namespace foo'', в то время как вы действительно должны писать: '' namespace foo {} ''. Использование пространства имен не совпадает с определением пространства имен. А также вам нужно «extern» C «' 'stuff внутри foo.cpp, иначе ваш компоновщик будет плакать. – BitTickler

+0

Благодарим вас, BitTickler, но это похоже на заявление #include foo.h в foo.cpp. Как я уже сказал, код отлично работает без спецификации пространства имен. – mdavidjohnson

+0

Вы не можете объявить код членом пространства имен в заголовке, а затем не добавлять код в пространство имен. '' namespace foo {void foofunc(); } ... namespace foo {void foofunc() {}} '' то, что вам нужно. – BitTickler

ответ

0

Вы запрашиваете связь C. Но C не имеет концепции пространства имен. Это похоже на конфликт интересов.

+0

Интересно (не каламбур). Я думал, что все, что я делал, используя внешнюю связь «С», устраняло название mangling. Я все еще компилирую с g ++, а не gcc. Поскольку мой окончательный план состоит в том, чтобы переписать foo.s и использовать его без файла .cpp, мне нужна ссылка C, потому что ассемблер ничего не узнает. Есть ли другой способ устранить (или хотя бы свести к минимуму) потенциальные столкновения имен? – mdavidjohnson

+0

Да, с '' extern '' вы определяете связь (и название mangling). Вы можете отлично иметь функции c-linkage внутри пространства имен. Не часто имеет смысл, но является законным. Вы не можете «обмануть» C-api, чтобы внезапно оказаться внутри пространства имен C++ (что, как я считаю, автор вопроса пытается). – BitTickler

0

fooPtr объявляется как глобально (в неназванном namespace), так и в namespace joke. Это разные сущности.

The using namespace joke затем сообщает компилятору использовать имена внутри joke в качестве кандидатов в соответствии идентификаторов

Имена ::fooPtr и joke::fooPtr являются видимыми для компилятора, когда код имеет заявление fooPtr = &fooStack[0] + 9. Значение using namespace joke означает, что совпадают как ::fooPtr, так и joke::fooPtr. Нет оснований предпочитать друг друга, поэтому компилятор отклоняет код из-за двусмысленности.

+0

Хорошо, теперь я действительно смущен. fooPtr появляется в скобках в пространстве имен в foo.h. Это следует за использованием шутки пространства имен; как в foo.cpp, так и в bar.cpp - где он появляется в неназванном пространстве имен? – mdavidjohnson

+0

Объявление 'fooPtr' в foo.h находится в пространстве имен' joke'. Объявление в файле foo.cpp находится в области файла, а не в любом пространстве имен, поэтому находится в неназванном пространстве имен. Предыдущее «использование шутки пространства имен» в foo.cpp не связывает последующее объявление/определение 'int * fooPtr' с пространством имен' joke'. – Peter

Смежные вопросы