Wann Namespace, und wie?
-
und wie sieht es mit verschiedenen headern aus?
Wie kann ich da mehrere in einen namensraum nehmen??
-
Ganz einfach wieder in den Namespace schreiben, also:
// class1.h namespace myns { class A { }; } // class2.h namespace myns { class B { }; }
Der Namespace wird dann einfach erweitert, nicht überschrieben, wie Du evtl. vermuten könntest.
-
ja das habe ich vermutet =)!
und ist die obige lösung, mit den .cpp dateien zu den .h dateien auch richtig?
-
Ja, Du kannst es so machen. Ich mache es z.B. eigentlich immer so:
2 Klassen, also 4 Dateien (class1.h, class2.cpp, class2.h, class2.cpp)
// class1.h #ifndef __CLASS1_H #define __CLASS1_H namespace myns { class class1 { ... }; } #endif // class1.cpp #include "class1.h" using namespace myns; class1::class1() { } ... // class2.h #ifndef __CLASS2_H #define __CLASS2_H namespace myns { class2 { ... }; } #endif // class2.cpp #include "class2.h" using namespace myns; class2::class2() { } ...
So hast Du für jede Klasse eine eigene Datei und die Struktur findest Du im Dateisystem wieder. Für den Namespace könntest Du ein Unterverzeichnis erstellen, wo Du dann die anderen Dateien reinpackst. Außerdem kannst Du noch eine alltemeine Headerdatei erstellen, wo dann alle Klassen und Funktionsdateien inkludiert werden.
// myns.h #ifndef __MYNS_H #define __MYNS_H #include "class1.h" #include "class2.h" ... #endif
Dann hast Du z.B. folgende Sturktur:
myns (verzeichnis) +- class1.cpp +- class1.h +- class2.cpp +- class2.h +- myns.h
Für ne Lib oder so finde ich das z.B. sehr übersichtlich und geordnet. Und wenn Du alles inkludieren möchtest, dann schreibst Du einfach
#include "myns\\myns.h"
und fertig.
Die Präprozessor-Anweisungen würde ich mit reinnehmen, da es ja schonmal sein kann, dass eine Headerdatei mehrmals inkludiert wird, z.B. bei Vererbung, so sicherst Du das mit ab. Ist so, denke ich, ziemlich strukturiert und sauber.
Wenn jmd. anderer Meinung ist, dann nur zu, wie gesagt, ich lerne auch noch.
-
so habb jetzt mal was probiert...geht nicht:
Da ich grad an einem seriennummernprogramm schreibe, habe ich die klassen mal so genannt!Fehler hab ich im Code benannt, unten steht Meldung dazu!
//serial_exception.h //--------------------------------------------------------------------------- #ifndef serial_exceptionH #define serial_exceptionH namespace serial { class MyException:public std::runtime_error { public: MyException(const std::string& msg):std::runtime_error(msg){} }; class MyException2:public std::runtime_error { public: MyException2(const std::string& msg):std::runtime_error(msg){} }; } //--------------------------------------------------------------------------- #endif
in der cpp steht nix drin, brauch ich ja nix!
//serial_func.h //--------------------------------------------------------------------------- #ifndef serial_funcH #define serial_funcH namespace serial { void Tester(); void ClassTester(Tserial &t); //Fehler 1 void ExceptionT(int z); } //--------------------------------------------------------------------------- #endif //serial_func.cpp //--------------------------------------------------------------------------- #pragma hdrstop #include <iostream> #include <conio> #include "serial_func.h" #include "serial_class.h" #include "serial_exception.h" using namespace std; using namespace serial; //--------------------------------------------------------------------------- void Tester() { cout<<"serial_func tester()"<<endl; } void ClassTester(Tserial& t) { t.TestIt(); } void ExceptionT(int z) { if(z==0) throw MyException("Fehler, Zahl ist 0"); else throw MyException2("Fehler: Exc2, Zahl groesser null"); } #pragma package(smart_init)
//serial_class.h //--------------------------------------------------------------------------- #ifndef serial_classH #define serial_classH namespace serial { class Tserial { public: void TestIt()const; }; } //--------------------------------------------------------------------------- #endif //serial_class.cpp //--------------------------------------------------------------------------- #pragma hdrstop #include "serial_class.h" #include <iostream> #include <conio> using namespace std; using namespace serial; //--------------------------------------------------------------------------- void Tserial::TestIt()const { cout<<"Namespace serial, klasse serial"<<endl; } #pragma package(smart_init)
//Hauptprogramm //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include <iostream> #include <conio> #include "serial_exception.h" #include "serial_func.h" #include "serial_class.h" using namespace std; using namespace serial; //--------------------------------------------------------------------------- #pragma argsused int main(int argc, char* argv[]) { ExceptionT(0); //wahrscheinlich Fehler2 hier getch(); return 0; } //---------------------------------------------------------------------------
So nun zu den Fehlermeldungen:
Fehler 1: "Parameterdeklaration darf nicht mit Tserial beginnen" Fehler 2: (linker Fehler) "Unresolved external 'serial::ExceptionT(int)' referenced from (Pfad---SERIAL.OBJ)
hoffe mir kann hier jemand helfen
-
du mußt in serial_func.h den header serial_class.h includen, weil du in serial_func.h die klasse Tserial verwendest. am besten du includest sie auch noch in serial_func.cpp. auf indirekte includes ("serial_class.h brauch ich ja in serial_func.cpp nicht zu includen, die ist ja schon in serial_func.h drin") solltest du dich nicht verlassen. es könnte ja sein, daß du serial_func.h mal änderst und dann ist serial_class.h vielleicht nicht mehr drin.
da du sie dort nicht includest, ist Tserial dort nicht deklariert und du bekommst die fehlermeldung, daß Tserial in der deklaration der funktionsparameter von ClassTester() nicht verwendet werden darf.
die zweite fehlermeldung rührt daher, daß aufgrund des ersten fehlers die datei serial_func.cpp nicht kompiliert wurde. und deswegen kann der linker die dort vorhandene funktion ExceptionT() auch nicht finden.
-
also ich hab das jetzt geändert, aber der 2te fehler ist immernoch da!
-
Du solltest auch die Definition von ExceptionT im Namensraum serial machen.
namespace serial { void ExceptionT(int z) { if(z==0) throw MyException("Fehler, Zahl ist 0"); else throw MyException2("Fehler: Exc2, Zahl groesser null"); } }
-
also geht es doch nicht wie mantiz geschrieben hat?
also ein using namespace reicht doch nicht?
Weil das habe ich ja in der cpp wo die definition der funktion ist gemacht!
-
Mit using namespace serial öffnest du den Namensraum serial in deiner cpp. Deswegen weiß der arme Compiler aber immer noch nicht wozu ExceptionT gehört. Das mußt du ihm schon sagen.
-
Ach, so meintest Du das. Sorry, dann hatte ich das falsch verstanden.
Mit "using namespace" kannst Du nur direkt auf die Elemente davon zugreifen, definiert werden müssen die aber dann schon vorher. Ich dachte Du meintest in der cpp-Datei sowas:using namespace myns { int test() { return 10; } ... }
das könntest Du dann so aufteilen:
// .h-File namespace myns { int test(); } // .cpp-File using namespace myns; int test() { return 10; }
Oder halt mit Klassen.
-
lol mantiz, irgendwie erklärst schonwieder das gleiche!
-
Ja eigentlich schon, aber ist das falsch?
ich dachte erst wellness meinte mit der Frage, ob man das auf cpp-Dateien übertragen könnte, dass man innerhalb der cpp-Datei sowas machen könnte:
namespace myns { ... }
aber er hatte es wohl so verstanden, dass man sich mit "using namespace ..." innerhalb der cpp-Datei in dem Namespace befindet, aber das ist ja nicht so, man kann dann nur direkt, also ohne den Namespace noch angeben zu müssen auf die Elemente davon zugreifen, die aber bereits existieren müssen. Erweitern kann man den Namespace so nicht.
Oder sehe ich da jetzt was falsch? Wie gesagt, so gross ist meine Erfahrung da jetzt auch noch nicht.
-
nee das siehst schon richtig...nur er meinte wohl was andres, und zwar, wie man die klassen methoden etc definiert!
Er wollte nicht nur auf den namespace zugreifen, sondern seine klassenmethoden implementieren!