Buchlisting über für exceptions fehlerhaft



  • Ist das wieder JW?


  • Mod

    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.


  • Mod

    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 string erzeugt und auf diesen c_str() aufgerufen. Der string existiert damit außerhalb von what() nicht mehr, so dass der char -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 ein what mit string -Rückgabe zu haben?



  • class KeineDatenMehr : public meaCulpa {
    public:
      KeineDatenMehr(int nr) : meaCulpa("Fehler nummer: " + std::to_string(nr)) { }
      virtual ~KeineDatenMehr() throw() {}
    };
    

    🙂


Anmelden zum Antworten