grundlegendes Verständnisproblem: namespace-Verwendung mit 2 Dateien ohne Header
-
Hallo, ich hab hier ein Verständnisproblem, bei dem ich Hilfe nötig hätte.
Folgender simpler Code kompiliert:Datei 1: ShopAuch.cpp
#include "stdafx.h" int countArticles() { return 3; }Datei 2: Run.cpp
#include "stdafx.h" #include <iostream> int countArticles(); int main() { int zahl = -1; zahl = countArticles(); std::cout << zahl << std::endl; // Pro Forma std::cout << "Och, schon zuende?"; getchar(); return 0; }Verwende ich jetzt aber in der Datei ShopAuch.cpp einen namespace:
#include "stdafx.h" namespace myshopauch{ int countArticles() { return 3; } }und benutze den namespace in Run.cpp
using namespace myshopauch;existiert dieser nicht. Die Direktive
#include ShopAuch.cppführt zu anderen Fehlern.
Definiere ich mir jetzt aber einen Header für die Datei ShopAuch.cpp mit namespace (und lösche die Vorwärtsdeklaration aus der Run.cpp) kompiliert das wunderbar.
Kann ich namespaces nur mit Headern verwenden? Was mach ich falsch?

-
PeterFragt schrieb:
...
myshopauch{shopauch;...
Gruß,
Simon2.
-
sorry, das war ein abtippfehler (der 4. arrrg), das ist es nicht.
-
Hi,
also ich würde mal die "precompiled Header"-Option rausnehmen (inkl. der "stdafx.h").
Das funktioniert nämlich manchmal nicht so gut und führt bisweilen zu solchen Phänomenen...Gruß,
Simon2.
-
Simon2 schrieb:
also ich würde mal die "precompiled Header"-Option rausnehmen (inkl. der "stdafx.h").
Das funktioniert nämlich manchmal nicht so gut und führt bisweilen zu solchen Phänomenen...Hallo, bringt leider nichts. Trotzdem Fehler.
Wenn ich die Direktive
#include "ShopAuch.cpp"rausnehme, kennt er den Namensraum nicht (using ...), und wenn ich sie reinehme behauptet der Compiler
error LNK2005: "int __cdecl myshopauch::countArticles(void)" (?countArticles@myshopauch@@YAHXZ) already defined in Run.obj
harrr

Ich könnte ja einfach einen Header benutzen, aber irg. macht mich das fuchsig
-
PeterFragt schrieb:
und wenn ich sie reinehme behauptet der Compiler
error LNK2005: "int __cdecl myshopauch::countArticles(void)" (?countArticles@myshopauch@@YAHXZ) already defined in Run.obj
Das ist nicht der Compiler, sondern der Linker.
Du solltest Funktionsdefinitionen nicht in Headerdateien schreiben (Ausnahme Templates oder
inline-Funktionen). Implementiere die Funktionen in .cpp-Dateien und schreibe nur die Deklaration in den Header.
-
Zu deiner Datei 2: Run.cpp
// ... namespace myshopauch{ int countArticles(); // Deklaration gehört auch in den Namensraum } // ...Ganz davon abgesehen das man immer mit Headern arbeiten sollte...
-
Die Deklaration der benutzten Objekte/Typen muß ja zur Compilezeit bekannt sein. In Deinem ursprünglich geposteten Beispiel ist aber in run.cpp keine Deklaration für countArticles vorhanden.
-
Nachtrag:
Das ist, als wenn ich
using namespace std;
benutzen würde, und dann mit zB string arbeiten wollte, ohne daß
#include <string>
vorhanden ist.
-
mh
Du solltest Funktionsdefinitionen nicht in Headerdateien schreiben
Wie kommst du darauf, dass ich das gemacht habe? Ich habe keine Header-Files mehr im Projekt.
Implementiere die Funktionen in .cpp-Dateien und schreibe nur die Deklaration in den Header
Damit ging es ja, ich will nur wissen, wieso das nicht ohne klappt.
Ganz davon abgesehen das man immer mit Headern arbeiten sollte...
Jau, ich war nur neugierig, warum/wie das ohne geht. Anscheinend nicht zu unrecht, weil es ja nicht problemlos klappte
namespace myshopauch{ int countArticles(); // Deklaration gehört auch in den Namensraum }Mh, die Deklaration (und Definition) findet doch in der ShopAuch.cpp statt?
-
#include <stdio.h> #include <string> #include <iostream> #include "ShopAuch.cpp" using namespace myshopauch; int countArticles(); int main() { int zahl = -1; zahl = countArticles(); std::cout << zahl << std::endl; // Pro Forma std::cout << "Och, schon zuende?"; getchar(); return 0; }Führt dazu, dass der Compiler (ja, wirklich der Compiler) meckert:
1>f:\visual studio 2008\projects\pointertest\pointertest\namespacetest\namespacetest.cpp(18) : error C2668: 'countArticles' : ambiguous call to overloaded function 1> f:\visual studio 2008\projects\pointertest\pointertest\namespacetest\namespacetest.cpp(11): could be 'int countArticles(void)' 1> f:\visual studio 2008\projects\pointertest\pointertest\namespacetest\shopauch.cpp(16): or 'int myshopauch::countArticles(void)' 1> while trying to match the argument list '(void)'
-
PeterFragt schrieb:
#include "ShopAuch.cpp"Wo lernt man denn so was?
Grundsätzliches für Ungeübte:
1. Deklaration gehört ins .h,
2. Definition ins .cpp.
3. das .h File mit #include guards ausstatten und
4. nur .h Files inkludieren
-
PeterFragt schrieb:
Wie kommst du darauf, dass ich das gemacht habe? Ich habe keine Header-Files mehr im Projekt.
Weil man normalerweise Headerdateien inkludiert und das ein sehr häufiger Fehler ist. Dadurch, dass du .cpp-Dateien inkludiert hast, hast du den gleichen Effekt erzielt. Diese inkludiert man aber nicht!
Wieso willst du auf Header verzichten, aber stattdessen .cpp-Dateien als Header missbrauchen?
-
PeterFragt schrieb:
Definiere ich mir jetzt aber einen Header für die Datei ShopAuch.cpp mit namespace (und lösche die Vorwärtsdeklaration aus der Run.cpp) kompiliert das wunderbar.
Das ist schon der richtige Weg.
-
Mh, irg. scheine ich mein Problem nicht gut rüberzubringen.
also ich hab einfach nur mit Namespaces (und 2 Dateien) rumgespielt und das klappte nur mit Header aber nicht ohne.
Da ich neugierig bin, hab ich den namespace weggelassen (ohne Header-Datei) und es klappte. Also kam ich auf den Gedanken, dass ich für einen Namespace immer einen Header benötige, und wenn nein, wieso ich das im Code nicht hinbekomme.Das mit dem cpp Dateien inkludieren war nur ein verzweifelter Versuch, weil sonst der (ich glaub) Compiler meldet, dass er den Namensraum nicht findet.
-
poste halt mal ein minimalbsp - und zwar nicht mit irgendwas drin, wie "alles andere ging nicht und dann hab ich halt einfach irgendwas hingeschrieben"...
dann können wir dir deinen fehler wahrscheinlich relativ schnell zeigen
bb
-
PeterFragt schrieb:
Mh, irg. scheine ich mein Problem nicht gut rüberzubringen.
also ich hab einfach nur mit Namespaces (und 2 Dateien) rumgespielt und das klappte nur mit Header aber nicht ohne.
Da ich neugierig bin, hab ich den namespace weggelassen (ohne Header-Datei) und es klappte. Also kam ich auf den Gedanken, dass ich für einen Namespace immer einen Header benötige, und wenn nein, wieso ich das im Code nicht hinbekomme.In der zu kompilierenden Datei brauchst Du Deklarationen für die Typen/Funktionen, die Du benutzen möchtest. In Deinem Beispiel ohne Namensraum hast Du eine entsprechende Deklaration in der run.cpp gehabt.
In Deinem Beispiel mit Namensraum ist keine Deklaration für die Funktion countArticles in der run.cpp. Das kann nicht kompiliert werden.
-
Mal zwischendrin ein Danke an alle für die Geduld

Minibeispiel, das nicht kompiliert:
#include <stdio.h> #include <string> #include <iostream> using namespace myshopauch; // einziger Unterschied mit Namespace, der nicht bekannt ist, wenn ich keinen Header verwende in der ShopAuch.cpp int countArticles(); // Vorwärtdeklaration int main() { int zahl = -1; zahl = countArticles(); return 0; }#include <stdio.h> #include <string> namespace myshopauch{ // Das hier weglassen und die using Anweisung und es kompiliert int countArticles() { return 3; } }Fehlermeldung:
1>f:\visual studio 2008\projects\pointertest\pointertest\namespacetest\namespacetest.cpp(7) : error C2871: 'myshopauch' : a namespace with this name does not exist
-
wenn du
int countArticles(); // Vorwärtdeklaration
schreibst, ist klar, dass es nicht geht...1. nimmt man dafür header und
2.:namespace mybla { int countArticles(); }bb
PS:
#include <stdio.h>
ist kein gültiges C++
der header (den du hier gar nicht brauchst) heißt <cstdio>und
int main() { /*...*/ return 0; //brauchst du nicht }edit - also so:
/*main.cpp*/ #include "foo.h" int main() { my::foo(); }/*foo.h*/ namespace my { void foo(); }/*foo.cpp*/ #include "foo.h" void my::foo() { /*...*/ }alternative für die foo.cpp:
/*foo.cpp*/ #include "foo.h" namespace my{ void foo() { /*...*/ } } //namespace my
-
Ich verstehe nicht, wieso du auf Header verzichten willst, es geht aber natürlich auch ohne, mit extern:
namespace XY { int test() { return 4; } }#include <iostream> using namespace std; namespace XY { extern int test(); } int main() { cout << XY::test() << endl; cin.get(); return 0; }Du musst den Namespace in beiden Dateien definieren, die Funktion muss mit extern deklariert werden, dann weiß der Compiler, dass sich der Linker darum kümmern muss, die Funktion zu finden.