grundlegendes Verständnisproblem: namespace-Verwendung mit 2 Dateien ohne Header
-
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.
-
Ad aCTa schrieb:
Ich verstehe nicht, wieso du auf Header verzichten willst, es geht aber natürlich auch ohne, mit extern:
[...][...] namespace XY { extern int test(); } [...]Das
externist hier überflüssig. eine Funktionsdeklaration in einem nicht-anonymen Namensraum führt automatisch schon einen Namen (hier "test") mit externer Bindung (external linkage) ein.Peter, Du vermischst hier verschiedene Konzepte, die nicht viel miteinander zu tun haben. Namensräume sind total unabhängig davon, wo und wie Quellcode gespeichert wird (im Gegensatz zu den Java Packages zum Beispiel). Das Konzept einer Übersetzungeinheit und was
#includeeigentlich macht, solltest Du Dir auch nochmal angucken. "Header-Dateien" sind auch nichts Besonderes. Den Compiler interessiert es nicht die Bohne, woher der Quellcode kommt. Das mit den Header-Dateien ist nur eine Konvention, die sich entwickelt hat -- eine gute Konvention. Ein anderes wichtiges Konzept ist die Bindung (linkage).In jedem guten C++ Buch sollte das alles geklärt werden. Man kann sich echt viel Zeit und Ärger sparen, wenn man das einfach mal nachließt. Ich weiß ja nicht, wie's Euch geht/ging, aber ich fand das höchst unbefriedigend, nicht den Durchblick bzgl Header, Namensräume, Bindung, "One-Definition-Rule", ... zu haben.
Gruß,
SP
-
Ad aCTa schrieb:
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.
Danke, jetzt klappt es!
Nochmal, bevor einige hier nicht schlafen können

Ich weiß, dass ich eine Header-Datei benutzen sollte, aber als es klappte war da diese Neugier, ob ich das auch ohne kann, so als Beweis. Und wie ihr seht konnte ich das nicht, also waren da wohl noch Lücken!Gerade für OOP sind explizite Schnittstellen ja durchaus eine sinnvolle Sache

Danke allen!
-
unskilled schrieb:
...
int main() { /*...*/ return 0; //brauchst du nicht }edit - also so:
/*main.cpp*/ #include "foo.h" int main() { my::foo(); }...
Naja - ich nutze trotzdem sehr gerne ein "überflüssiges return", weil
a) es sowieso nur bei main und 0 funktioniert (ist mir schon mehr als einmal passiert, dass main() später zu einer anderen Funktion wurde)
b) es üblicherweise sowieso eine meiner ersten Überlegungen ist, wann eine Funktion was zurückliefern soll; da wird das Weglassen eher zu einem künstlichen "Kunsttrick".Aber es stimmt natürlich: Man darf es weglassen (und Viele wissen das nicht).
Gruß,
Simon2.
-
warum erlaubt der Compiler das denn, wenn ich als Signatur auch
main():voidbenutzen kann?
-
PeterFragt schrieb:
warum erlaubt der Compiler das denn, wenn ich als Signatur auch
main():voidbenutzen kann?
Falls Du
void main();meinst: Weil er auch nicht standardkonforme Dinge zulässt (und sie "irgendwie" interpretiert).
Gruß,
Simon2.