Ausnahmen und Referenzen



  • Hi!
    Neulich habe ich etwas in einem Buch gelesen, vom Prinzip her:

    class irgendwas {};
    
    try
    {
    throw irgendwas();
    }
    catch(irgendwas& e)
    {
    ...
    }
    

    Sind Referenzen dort möglich? Bei Funktionen ist's klar, dass die keine Referenzen auf lokale Variablen zurückgeben können, aber wie ist das bei Exceptions? Läuft das da anders ab?



  • Klar!

    #include <conio.h>
    #include <iostream>
    
    int main()
    {
      class irgendwas
      {
        public:
          void print() { std::cerr << "catch as catch can." << std::endl; }
      }; 
    
      try 
      { 
        throw irgendwas(); 
      } 
      catch(irgendwas& e) 
      { 
        e.print();
      }
      getch();
    }
    

    Normalerweise liegt die Exception-Klasse außerhalb von main():

    #include <iostream>
    #include <string>
    #include <conio.h>
    
    class Number_format
    {
      private:
        std::string what_;
      public:
        Number_format() : what_("Typumwandlung misslungen") {}
        Number_format(std::string s) : what_(s) {}
        std::string getwhat(){ return what_; }
    };
    
    long string_to_long(std::string str)
    {
      char pos = 0;
      if (str.empty()) throw Number_format();
      if (str[0] == '-') ++pos;
      if (str[pos] < 48 || str[pos] > 57) throw Number_format();
      return std::strtol(str.c_str(), NULL, 10);
    }
    
    int main()
    {
      std::string s;
    
      try
      {
        std::cout << "Geben Sie eine Zahl ein: ";
        std::cin >> s;
        std::cout << string_to_long(s) << std::endl;
      }
      catch (Number_format& ex)
      {
        std::cerr << ex.getwhat() << std::endl;
      }
      getch();
    }
    


  • Sind Referenzen dort möglich?

    Nicht nur möglich sondern guter Stil. Besser sind natürlich noch Referenzen-auf-const.

    Bei Funktionen ist's klar, dass die keine Referenzen auf lokale Variablen zurückgeben können, aber wie ist das bei Exceptions?

    Ein throw bla() wirft immer by value. Das Exception-Objekt wird also über seinen Copy-Ctor kopiert. Das Laufzeitsystem übernimmt die Kopie und garantiert ihre Gültigkeit solange die Exception aktiv ist.

    Du wirfst also hier keine lokale Variable sondern eine Kopie von dieser. Aus diesem Grund heißt eine Regel auch "throw by value, catch by reference".

    void bla()
    {
        Blub b;
        throw &b;
    }
    

    Hier hast du jetzt in der Tat ein großes Problem, da du ein Verweis auf ein lokales Objekt wirfst. Dieses Objekt stirbt aber mit dem Verlassen von bla und darf demzufolge nie mehr in einem catch-Block referenziert werden.

    Also:
    Exceptions immer schön by value werfen (-> Exceptionklassen brauchen einen Copy-Ctor) und by reference(-to const) fangen.



  • Ei wie fein 😃
    Dann müsste ja auch im Vergleich zu catch by value ein Kopieren wegfallen, und slicing wird auch vermieden 🙂



  • Dann müsste ja auch im Vergleich zu catch by value ein Kopieren wegfallen, und slicing wird auch vermieden

    Genaus so ist es 🙂



  • Danke, wieder was gelernt 🙂


Anmelden zum Antworten