Einige Fragen zu Klassen und istream
-
Hallo,
Ich habe gerade angefangen, mich mit Klassen zu beschäftigen.
Meine Klasse sieht in etwa so aus:class Klasse { private: std::string a; std::string b; public: Klasse(const char* x, const char* y); friend std::istream& operator >> (std::istream& is, Klasse& op); //diverse andere konstruktoren, operatorüberladungen und memberfunktionen };Die erste Frage wäre: Wie muss hier der Destruktor aussehen?
Reicht ein einfaches ~Klasse() {} oder muss im Destruktor noch irgendetwas besonderes stehen?Die zweite Frage ist, ob ich den char-Zeiger des Konstruktors löschen muss:
Klasse::Klasse(const char* x, const char* y) : a(x), b(y) { //hier char * x und y löschen? }Die dritte Frage wäre, wie ich "if" überladen kann, sodass if(objekt) funktioniert (den ! Operator habe ich schon überladen; if(!objekt) klappt also)
Die letzte Frage bezieht sich auf das Überladen des >> Operators. Im Moment habe ich das so gelöst:
std::istream& operator >> (std::istream& is, Klasse& op) { is >> op.a; is >> op.b; return is; }Das Problem dabei ist, dass string b aus mehreren Wörtern bestehen kann. Bei der Eingabe von zB "StringA StringB1 StringB2" wird natürlich nur StringB1 eingelesen. Als Lösung hatte ich mir überlegt, mit getline zu arbeiten. Da der >> operator aber sowohl mit cin als auch beim Einlesen von Daten aus Dateien funktionieren soll, weis ich nicht genau, wie ich das einrichten soll. Hat da irgendjemand eine Idee?
Schonmal Danke im Voraus!

-
clasy schrieb:
Wie muss hier der Destruktor aussehen?
Reicht ein einfaches ~Klasse() {} oder muss im Destruktor noch irgendetwas besonderes stehen?Im Destruktor muss per Definition nix stehen. Wenn du z.B. Speicher alloziert hast (z.B. im Konstruktor), dann kannst (und solltest) du ihn im Destruktor wieder freigeben.
clasy schrieb:
Die zweite Frage ist, ob ich den char-Zeiger des Konstruktors löschen muss:
Klasse::Klasse(const char* x, const char* y) : a(x), b(y) { //hier char * x und y löschen? }Den Zeiger "löschen" geht ja nicht. Das ist einfach eine lokale Variable, die mit dem Ende der Funktion (hier Konstruktor) ihre Gültigkeit verliert. Wenn du aber meinst, ob du den Speicherbereich, auf den der Zeiger zeigt, freigeben sollst: keine Ahnung!
Ich weiß ja nicht, woher x und y kommen. Normalerweise würde ich aber sagen, dass der Speicherbereich unbedingt an der Stelle freigegeben werden sollte, an der er auch angefordert wurde. Da das nicht in deiner Klasse passiert, sollte deine Klasse auch nix freigeben. Aber mal eine andere Frage: woher kommen denn diese Zeiger? Und sind die noch gültig, während deine Klasse Bestand hat? Wenn du irgendwelche (nicht-globale) Strings übergeben willst, dann sollte deine Klasse sich vielleicht besser eine Kopie davon machen. Denn wenn du nur die Zeiger speicherst und der Bereich, auf den gezeigt wird, nicht mehr gültig ist, dann hast du ein Problem.clasy schrieb:
Die dritte Frage wäre, wie ich "if" überladen kann
Imho nicht. if ist keine Funktion und kein Operator.
-
clasy schrieb:
Die dritte Frage wäre, wie ich "if" überladen kann, sodass if(objekt) funktioniert (den ! Operator habe ich schon überladen; if(!objekt) klappt also)
Dafür musst du nicht
ifüberladen, sondern in der Klasse einen Cast-Operator zu einem alsboolinterpretierbaren Typen bereitstellen.class Klasse { public: operator bool () const; // naheliegendste Möglichkeit operator void* () const; // sicherer, siehe Safe Bool Idiom explicit operator bool () const; // beste Variante, aber erst in C++09 möglich };Dafür solltest du den
operator!nicht überladen, der ist nämlich nicht mehr nötig, wenn du einenboolhast.
-
Danke schonmal für die antworten!
Der Konstruktor
Klasse::Klasse(const char* x, const char* y) : a(x), b(y) { //hier char * x und y löschen? }soll bewirken, dass im programm dann
Klasse Objekt("stringA", "stringB");funktioniert. Die c-strings sind somit nur nötig, um "stringA" und "stringB" in die eigenschaften (also die std::strings) der Klasse umzuwandeln und werden nicht weiter benötigt.
Muss ich den konstruktor jetzt um eindelete [] x; delete [] y;erweitern, oder wird der von den c-strings angeforderte Speicherplatz beim verlassen des Konstruktors eh freigegeben?
-
Nein, du darfst Stringliterale nicht löschen. Diese werden automatisch beim Beenden des Programms freigegeben.
Falls der Aufrufer aber
char-Arrays dynamisch anfordert, ist er auch selber für deren Freigabe verantwortlich. Das ist nicht mehr Aufgabe des Konstruktors.
-
Der wird selbst verwaltet. Da musst du dir keine Sorgem machen.
-
Jetzt wurden alle Probleme gelöst, bis auf das letzte

Falls noch nicht klar wurde, was ich gemeint habe, noch mal ein anderes Beispiel:
Meine Klasse hat zwei Eigenschaften: std::string a und std::string b.
string a nimmt nur ein einzelnes Wort (eine ID) auf, während string b einen Namen aufnehmen soll, der durchaus aus mehreren wörtern bestehen kann.
Die Datei, aus der ich Auslesen will, sieht ungefähr so aus:SADJ Name des ersten Objekts AS Name des zweiten Objektswenn ich ein Objekt über den >> Operator einlesen will, soll string a="SADJ" und string b="Name des ertes Objekts" sein. Im Moment habe ich das folgendermaßen gelöst:
std::istream& operator >> (std::istream& is, Klasse& op) { is >> op.a; is >> op.b; return is; }Der Vorteil davon ist, dass ich so sowohl mit dem Einlesen aus Dateien arbeiten kann, als auch mit Eingaben vom Benutzer über std::cin. Der Nachteil dabei ist natürlich, dass string b immer nur "Name" sein wird, da das Einlesen des strings ja beim Leerzeichen unterbrochen wird.
Die Einzige Lösung, die ich sehe, wäre mit getline zu arbeiten. Ich weis allerdings nicht, wie ich getline so benutzte, dass es sowhol für das Einleisen aus Dateien ALS AUCH für die Benutzeringaben über cin gültig ist.string str; cout << "Name des Objekts: "; getline (cin,str); //ganze Zeile über cin einlesen ifstream lesen; string dateiname="test.txt"; lesen.open(dateiname.c_str(), ios_base::in); getline(lesen, str); //ganze Zeile aus Datei einlesenHat jemand eine Idee, wie ich den >> Operator so überlade, dass er eine ganze Zeile sowohl aus einer Datei als auch über cin einliest?
-
Hat sich erledigt, lösung war einfach
std::istream& operator >> (std::istream& is, Klasse& op) { std::string tmp; getline(is, tmp); return is; }