Buchlisting über für exceptions fehlerhaft
-
Ist das wieder JW?
-
Bashar schrieb:
Ist das wieder JW?
Nein, Willemer. Anscheinend auch nicht besser
-
Danke euch! Ich habe es mittlerweile geschafft, den Quelltext zu korrigieren. Allerdings verstehe ich nicht, warum diese Version nicht funktioniert.
Ich habe schliesslich das Stringstreamobjekt innerhalb der Klasse deklariert, sodass es bei der Rückkehr der Funktion nicht gelöscht werden sollte.Folgenden Fehler bekomme ich von meinem Compiler:
1>d:\programme\microsoft visual studio 10.0\vc\include\sstream(724): error C2248: "std::basic_ios<_Elem,_Traits>::basic_ios": Kein Zugriff auf private Member, dessen Deklaration in der std::basic_ios<_Elem,_Traits>-Klasse erfolgte.
#include <iostream> #include <exception> #include <string> #include <sstream> using namespace std; // Meine eigene Basisklasse, abgeleitet von exception class meaCulpa : public exception { public: meaCulpa(string s) {this->s = s;} virtual ~meaCulpa() {} virtual const char * what() {return s.c_str();} private: string s; }; // Besonderer Fehler, wenn keine Daten mehr vorliegen class KeineDatenMehr : public meaCulpa { public: KeineDatenMehr(int a) : meaCulpa(" ") {nr = a;} virtual ~KeineDatenMehr(){} virtual const char * what(); private: int nr; stringstream myStream; //stringstream ist jetzt innerhalb der Klasse, string s gelöscht }; // what() wird für eigene Fehlermeldung überschrieben const char * KeineDatenMehr::what() { myStream << "Keine Daten mehr. Fehlernr.: " << nr; return myStream.str().c_str(); } // Eine weitere Fehlerart wird von meaCulpa abgeleitet. class QuelleFehlt : public meaCulpa { public: QuelleFehlt() : meaCulpa("Quelle fehlt") {} }; // Tuwas simuliert die beiden Fehlerarten in Abhängigkeit vom // Parameter void Tuwas(int Problem) { if (Problem==0) { throw KeineDatenMehr(8); } if (Problem==1) { throw QuelleFehlt(); } } int main() { // Problem-Nummer eingeben int Auswahl; cout << "Zahl zwischen 0 und 3 eingeben:" << endl; cin >> Auswahl; // Der try-Block fängt die Exception in Tuwas try { Tuwas(Auswahl); } // Fängt nur die eigenen Fehler catch(meaCulpa& fehler) { cout << fehler.what() << endl; } cin.ignore(std::numeric_limits<streamsize>::max(), '\n'); cin.get(); }
-
Da dürfte es um den Kopierkonstruktor gehen. Die Streams sind generell nicht kopierbar. Wenn jetzt der Compiler für deine Klasse KeineDatenMehr einen Kopierkonstruktor generiert, ruft er dort drin die Kopierkonstruktoren aller Membervariablen auf ... aber stringstream besitzt keinen bzw. lediglich einen, der private ist.
Ich seh auch nicht ganz, wozu das gut sein soll. Speicher dir doch den String und nicht den Stream...
-
Ok, ich dachte ich könnte damit den Speicherplatz für den String sparen, aber das ist eigentlich irrelevant, weil der Stringstream eh nach der Ausführung der Funktion gelöscht wird...
-
Und der Stream belegt wohl keinen Speicher?

Ich würde mal vorschlagen: Wegwerfen und neumachen. Es sei denn du hast Spaß daran das verkorkste Vorbild aus dem Buch glattzuziehen.
-
Ich würde mal vorschlagen: Wegwerfen und neumachen. Es sei denn du hast Spaß daran das verkorkste Vorbild aus dem Buch glattzuziehen.
Da hast du wohl oder übel recht

Und der Stream belegt wohl keinen Speicher?

Den Stream brauche ich ja so oder so zum Erstellen des strings für what(). Den String würde ich theoretisch nicht benötigen, wenn ich den String innerhalb der Funktion über sstream.str().c_str() zurückgeben könnte.
-
Gib doch bei what() einfach einen String zurück, anstatt einem char*.
-
Buchleser schrieb:
Und der Stream belegt wohl keinen Speicher?

Den Stream brauche ich ja so oder so zum Erstellen des strings für what().
Aber nur lokal. Ich dachte es ginge dir um den Speicher, den das Exception-Objekt benötigt.
Mir fällt übrigens grade ein, dass es auch nicht gehen würde, wenn stringstream kopierbar wäre.
Bei
return sstream.str().c_str();wird ja ein temporärer
stringerzeugt und auf diesenc_str()aufgerufen. Derstringexistiert damit außerhalb vonwhat()nicht mehr, so dass derchar-Zeiger ungültig ist.SeppJ schrieb:
Gib doch bei what() einfach einen String zurück, anstatt einem char*.
Er hält sich an die Vorgabe von
std::exception. Würdest du deine eigene Exception-Hierarchie nebenher bauen, um einwhatmitstring-Rückgabe zu haben?
-
class KeineDatenMehr : public meaCulpa { public: KeineDatenMehr(int nr) : meaCulpa("Fehler nummer: " + std::to_string(nr)) { } virtual ~KeineDatenMehr() throw() {} };