Eigene Ableitung von exception und Problem mit what()



  • Tippgeber schrieb:

    beruhiger schrieb:

    unskilled schrieb:

    Eigentlich sollte man das nie machen, weil damit der Sinn von namespaces total ausgehebelt wird...

    nicht gleich wieder in die üblichen muster verfallen. bei den wenigen zeilen code in lehrbüchern ist das noch OK und übersichtlicher. so viel felxibilität muss sein.

    Das ist der Fehler vieler Lehrbücher, wenn man im Lehrbuch nicht lernt wie man es sauber und ordentlich macht, wie soll man es dann lernen?
    Im Lehrbuch ist Schlamperei fehl am Platz.

    ich zitiere mich selbst: so viel flexibilität muss sein.
    beides ist sauber und ordentlich. in produktivem code machst du es einfach, denn es steckt ja keine großartige geistige leistung dahinter und in so kleinen testprogrammen sparst du dir die schreibarbeit. wo ist das problem? in büchern sieht es ohne das std:: zeug auch etwas übersichtlicher aus. machen wir aber kein drama draus - wollte das "nie" nur etwas relativieren -



  • Hallo zusammen,

    erstmal vielen Dank für Eure Hilfe. Das Buch um das es hier geht heist "Einstieg in C++" von Galileo Computing.
    Die Sache mit "using namespace std" in der Header Datei ist auf meinem Mist gewachsen. Im Buch ist alles in einer cpp Datei und ich wollte das trennen.
    Wenn ich Euch richtig verstanden habe, dann kann das mit dem Zurückgeben von const char* so wie das im Buch beschrieben ist nicht funktionieren ?!

    Ich habe jetzt 2 Sachen ausprobiert, aber beides haut auch nicht hin:

    // Meine eigene Basisklasse, abgeleitet von exception
    class meaCulpa : public exception
    {
    public:
    	ostringstream getNr;
    	meaCulpa(string s) {this->s = s;}
    	virtual ~meaCulpa() throw() {}
    	virtual const char* what() const throw()
    		{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() throw() {}
    	virtual const char* what() const throw();
    private:
    	int nr;
    	string s;
    };
    
    // what() wird für eigene Fehlermeldung überschrieben
    const char* KeineDatenMehr::what() const throw()
    {
    // Mit ostringstream als member kommt diese Fehlermeldung
      getNr << "Error No.: " << nr;
    [C++ Fehler] Unit1.cpp(46): E2094 'operator<<' ist im Typ 'ostringstream' für Argumente des Typs 'char *' nicht implementiert
    
    // Mit dieser Variante wird s angemeckert
      ostringstream getNr;
      getNr << "Error No.: " << nr;
      s = getNr.str();
    [C++ Fehler] Unit1.cpp(45): E2285 Keine Übereinstimmung für 'string::operator =(string)' gefunden
    
      //return s.c_str();
      return getNr.str().c_str();
    }
    


  • #include<sstream>
    


  • Lies halt wenigstens mal die Antworten durch...

    unskilled schrieb:

    Im CTor weist man imho dem string schon den kompletten Text zu - sonst wirds auch mit dem what() const schwer ;o)

    d.h.:

    //KeineDatenmehr.h
    
    #ifndef KEINEDATENMEHR_INCLUDED
    #define KEINEDATENMEHR_INCLUDED
    
    class KeineDatenmehr : public deinebasisklasse
    {
    public:
     KeineDatenmehr (int a);
    };
    
    #endif //#ifndef KEINEDATENMEHR_INCLUDED
    
    /*KeineDatenmehr.cpp*/
    
    #include "KeineDatenmehr.h"
    
    #include <sstream>
    
    KeineDatenmehr::KeineDatenmehr (int a)
    {
     std::stringstream ss;
     ss << "Fehlernr.: " << a;
     deinmemberstring = a.str();
    }
    

    Kannst auch beides in die *.h schreiben...

    const char* KeineDatenmehr::what () const throw()
    {
     return deinmemberstring.c_str();
    }
    

    Das hier ist bereits in der basisklasse implementiert - ist also sinnlos, es zu überschreiben - weiß auch nicht mal, ob das what() überhaupt virtual ist...

    bb

    edit:
    #include<sstream>
    Danke Drakon, auch wenns nicht für mich war 😉



  • unskilled schrieb:

    #include<sstream>
    Danke Drakon, auch wenns nicht für mich war 😉

    np. Stehts zu Diensten.;)



  • @drakon: Diesen include Befehl hatte ich drin, hab nur nicht mehr alles kopiert.

    @unskilled: Danke für Deine Hilfe, aber ich raff es einfach nicht. Ich hab mir den Code noch mal von der Webseite http://www.willemer.de/informatik/cpp/exceptions.htm kopiert und angepasst, aber jetzt wirft der Compiler in Zeile 29 einen Fehler aus. Keine Ahnung was er da mit "stringbuf" meint ?

    //---------------------------------------------------------------------------
    #ifndef Unit2H
    #define Unit2H
    #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() throw() {}
        virtual const char * what() const throw()
            {return s.c_str();}
    private:
        string s;
    };
    
    // Besonderer Fehler, wenn keine Daten mehr vorliegen
    class KeineDatenMehr : public meaCulpa
    {
    public:
        ostringstream getNr;
    	KeineDatenMehr(int a) : meaCulpa(" ") {nr = a; getNr << "Error No.: " << nr;}
        virtual ~KeineDatenMehr() throw() {}
        virtual const char * what() const throw();
    private:
        int nr;
        string s;
    };
    
    // what() wird für eigene Fehlermeldung überschrieben
    const char * KeineDatenMehr::what() const throw()
    {
      return getNr.str().c_str();
    }
    
    // Eine weitere Fehlerart wird von meaCulpa abgeleitet.
    class QuelleFehlt : public meaCulpa
    {
    public:
        QuelleFehlt() : meaCulpa("Quelle fehlt") {}
    };
    //---------------------------------------------------------------------------
    #endif
    

    Jetzt bekomme ich den Fehler:
    [C++ Fehler] Unit2.h(29): E2125 Compiler konnte Konstruktor kopieren nicht für die Klasse 'stringbuf' generieren



  • ok - seiht so aus, als ob die Seite ein wenig... komisch wäre ^^

    const char * KeineDatenMehr::what() const throw()
    {
      ostringstream getNr;
      getNr << "Keine Daten mehr. Fehlernr.: " << nr;
      return getNr.str().c_str();
    }
    

    Kann nicht funktionieren - also kann schon - das Verhalten ist einfach mal undefiniert.
    Mein Vorschlag: Leg dir nen ordentliches Buch zu ^^
    Wenn englisch kein prob ist, dann wäre mein Vorschlag ja "Programming - Principles and Practise Using C++" von Bjarne Stroustrup - obwohl ich noch nicht viel davon gelesen hab ^^
    Ansonsten gibts iwo in der FAQ oder so auch Bücher-Vorschläge...

    aber jetzt wirft der Compiler in Zeile 29 einen Fehler aus. Keine Ahnung was er da mit "stringbuf" meint ?

    Vll solltest du dann die Stelle mal posten ^^ Ich seh hier nix mit stringbuf 😛

    bb



  • unskilled schrieb:

    aber jetzt wirft der Compiler in Zeile 29 einen Fehler aus. Keine Ahnung was er da mit "stringbuf" meint ?

    Vll solltest du dann die Stelle mal posten ^^ Ich seh hier nix mit stringbuf 😛

    bb

    Die Stelle hab ich gepostet. Es ist im Listing oben auch die Zeile 29 !



  • C++ Learner schrieb:

    unskilled schrieb:

    aber jetzt wirft der Compiler in Zeile 29 einen Fehler aus. Keine Ahnung was er da mit "stringbuf" meint ?

    Vll solltest du dann die Stelle mal posten ^^ Ich seh hier nix mit stringbuf 😛

    bb

    Die Stelle hab ich gepostet. Es ist im Listing oben auch die Zeile 29 !

    virtual ~KeineDatenMehr() throw() {}
    Ich seh da nix mit stringbuf...
    Also poste mal die genaue Fehlermeldung, pls ^^

    bb



  • unskilled schrieb:

    virtual ~KeineDatenMehr() throw() {}
    Ich seh da nix mit stringbuf...
    Also poste mal die genaue Fehlermeldung, pls ^^

    bb

    Aber den Fehler hab ich doch gepostet:
    C++ Fehler] Unit2.h(29): E2125 Compiler konnte Konstruktor kopieren nicht für die Klasse 'stringbuf' generieren
    Der Compiler zeigt exakt diese Zeile an, und ich verwende keine Variable mit Namen stringbuf ??? Aber wahrscheinlich stolpert er über die Zeile 28, die hab ich ja so geändert.



  • du hast nen

    ostringstream getNr;

    als Member
    Der hat offenbar keinen Copy-CTor

    Verstehe nicht, warum er dir dann ne andere Zeile sagt, nur weil er den Copy-CTor nicht erstellen kann ><
    Wenn die Fehlermeldung nicht länger war, würd ich ma drüber nachdenken, ob ich mir ne andere IDE zulege ^^

    also musst du noch selbst nen Copy-CTor schreiben:

    ist aber nen schlechter Workaround - ich hab dir doch geschrieben, wie es geht...

    class KeineDatenMehr : public meaCulpa
    {
    public:
        KeineDatenMehr(int a) : meaCulpa(" ") {nr = a; getNr << "Error No.: " << nr;}
    
        KeineDatenMehr (const KeineDatenMehr& rhs)
        : s (rhs.s), nr (rhs.nr) {}
    
        virtual ~KeineDatenMehr() throw() {} //wie gehabt
        virtual const char * what() const throw(); //wie gehabt
    private:
        int nr;
        string s;
    
        ostringstream getNr; //private !
    };
    

    Wo lag das Prob an meiner Lösung für dein Problem?

    bb



  • unskilled schrieb:

    Wo lag das Prob an meiner Lösung für dein Problem?

    bb

    Du meinst die Lösung mit s.c_str(); ? Das hat auch nicht hingehauen, da bekomme ich nur ".:" ausgegeben:

    *.h

    //---------------------------------------------------------------------------
    #ifndef Unit2H
    #define Unit2H
    #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() throw() {}
        virtual const char * what() const throw()
            {return s.c_str();}
    private:
        string s;
    };
    
    // Besonderer Fehler, wenn keine Daten mehr vorliegen
    class KeineDatenMehr : public meaCulpa
    {
    public:
    	KeineDatenMehr(int a);
    	virtual ~KeineDatenMehr() throw() {}
        virtual const char * what() const throw();
    private:
        int nr;
        string s;
    };
    
    // what() wird für eigene Fehlermeldung überschrieben
    const char * KeineDatenMehr::what() const throw()
    {
      return s.c_str();
    }
    
    // Eine weitere Fehlerart wird von meaCulpa abgeleitet.
    class QuelleFehlt : public meaCulpa
    {
    public:
        QuelleFehlt() : meaCulpa("Quelle fehlt") {}
    };
    //---------------------------------------------------------------------------
    #endif
    

    *.cpp

    //---------------------------------------------------------------------------
    
    #pragma hdrstop
    
    #include "Unit2.h"
    
    //---------------------------------------------------------------------------
    
    #pragma package(smart_init)
    
    KeineDatenMehr::KeineDatenMehr(int a) : meaCulpa(" ")
    {
     nr = a;
     s = "Error No.: " + nr;
    // getNr << "Error No.: " << nr;
    }
    

    Also wenn ich ja nicht schon andere Beispiele mit C++ Klassen probiert hätte, dann würde ich jetzt die Flinte ins Korn werfen. Ich dachte das ist ein gutes Beispiel eine eigene Ableitung von exception, aber das hab ich mir einfacher vorgestellt 🕶



  • Dann guck mal an, was ich im CTor noch gemacht hab - btw:
    Das ganze, was du dort siehst ist iwie schwachsinnig...

    class KeineDatenMehr : public meaCulpa
    {
    public:
        KeineDatenMehr(int a);
        virtual ~KeineDatenMehr() throw() {}
        virtual const char * what() const throw();
    private:
        int nr;
        string s;
        //string meaCulpa::s;
        //const char* meaCulpa::exception::XXXX; //beim msvc ist es '_m_what'
    };
    

    ein string würde es also vll auch tun... wobei der msvc ja iwie auch mehrere strings benutzt (string _Str @logic_error; const char *_m_what @exception)...

    und auch die exception an sich hört sich so an, als ob es keine Ausnahme wäre, sondern ein sicheres Ereignis - der falsche Platz für Exceptions, wie ich finde...

    bb


Anmelden zum Antworten