Frage

Wird die folgende append () in dem Fang Ursache der erneut ausgelöst Ausnahme die Wirkung von append zu sehen () aufgerufen wird?

try {
  mayThrowMyErr();
} catch (myErr &err) {
  err.append("Add to my message here");
  throw; // Does the rethrow exception reflect the call to append()?
}

Und falls ich es auf diese Weise umschreiben, Willen Bit-Slice auftreten, wenn die tatsächliche Ausnahme von Myerr abgeleitet ist?

try {
  mayThrowObjectDerivedFromMyErr();
} catch (myErr &err) {
  err.append("Add to my message's base class here");
  throw err; // Do I lose the derived class exception and only get myErr?
}
War es hilfreich?

Lösung

In beiden Fällen, da man durch Bezugnahme fängt, werden Sie effektiv den Zustand des ursprünglichen Ausnahmeobjekts zu verändern (die man als wohnhaft in denken kann, 0x98e7058) wird reflektiert der Aufruf von append ()

  • Im zweiten Fall, da Sie etwas explizit werfen, eine Kopieren von err wird dann neu geworfen geschaffen werden (bei einer anderen „magischer Ort“ 0x98e70b0 - weil alle für die Compiler weiß err könnte sein ein Objekt auf dem Stapel über abgewickelten zu sein, wie e bei 0xbfbce430 war, nicht in dem „magischen Ort“ an 0x98e7058), so finden Sie abgeleitete klassenspezifische Daten während des Kopier-Bau verlieren eine Basisklasse-Instanz.
  • Einfaches Programm zu veranschaulichen, was passiert ist:

    #include <stdio.h>
    
    struct MyErr {
      MyErr() {
        printf("  Base default constructor, this=%p\n", this);
      }
      MyErr(const MyErr& other) {
        printf("  Base copy-constructor, this=%p from that=%p\n", this, &other);
      }
      virtual ~MyErr() {
        printf("  Base destructor, this=%p\n", this);
      }
    };
    
    struct MyErrDerived : public MyErr {
      MyErrDerived() {
        printf("  Derived default constructor, this=%p\n", this);
      }
      MyErrDerived(const MyErrDerived& other) {
        printf("  Derived copy-constructor, this=%p from that=%p\n", this, &other);
      }
      virtual ~MyErrDerived() {
        printf("  Derived destructor, this=%p\n", this);
      }
    };
    
    int main() {
      try {
        try {
          MyErrDerived e;
          throw e;
        } catch (MyErr& err) {
          printf("A Inner catch, &err=%p\n", &err);
          throw;
        }
      } catch (MyErr& err) {
        printf("A Outer catch, &err=%p\n", &err);
      }
      printf("---\n");
      try {
        try {
          MyErrDerived e;
          throw e;
        } catch (MyErr& err) {
          printf("B Inner catch, &err=%p\n", &err);
          throw err;
        }
      } catch (MyErr& err) {
        printf("B Outer catch, &err=%p\n", &err);
      }
      return 0;
    }
    

    Ergebnis:

      Base default constructor, this=0xbfbce430
      Derived default constructor, this=0xbfbce430
      Base default constructor, this=0x98e7058
      Derived copy-constructor, this=0x98e7058 from that=0xbfbce430
      Derived destructor, this=0xbfbce430
      Base destructor, this=0xbfbce430
    A Inner catch, &err=0x98e7058
    A Outer catch, &err=0x98e7058
      Derived destructor, this=0x98e7058
      Base destructor, this=0x98e7058
    ---
      Base default constructor, this=0xbfbce430
      Derived default constructor, this=0xbfbce430
      Base default constructor, this=0x98e7058
      Derived copy-constructor, this=0x98e7058 from that=0xbfbce430
      Derived destructor, this=0xbfbce430
      Base destructor, this=0xbfbce430
    B Inner catch, &err=0x98e7058
      Base copy-constructor, this=0x98e70b0 from that=0x98e7058
      Derived destructor, this=0x98e7058
      Base destructor, this=0x98e7058
    B Outer catch, &err=0x98e70b0
      Base destructor, this=0x98e70b0
    

    Siehe auch:

    Andere Tipps

    Diese Frage ist ziemlich alt und hat eine Antwort entsprechend der Zeit, es wurde gefragt. Allerdings mag ich nur eine Notiz auf hinzuzufügen, wie richtige Ausnahmebehandlung zu tun, da C ++ 11 und ich glaube, dies entspricht sehr gut zu dem, was Sie versuchen, mit dem Anfügen Funktion zu erreichen:

    Verwenden Sie std::nested_exception und std::throw_with_nested

    Es wird auf Stackoverflow beschrieben hier und hier , wie können Sie einen Backtrace auf Ausnahmen für einen Debugger, ohne dass in Ihrem Code oder umständliche Protokollierung, indem Sie einfach einen richtigen Exception-Handler schreiben, die verschachtelten Ausnahmen erneut auslösen wird .

    Da Sie dies mit jeder abgeleitete Exception-Klasse tun können, können Sie eine Vielzahl von Informationen zu einem solchen Backtrace hinzuzufügen! Sie können auch einen Blick auf meine MWE auf GitHub , wo ein Backtrace etwas aussehen würde, folgt aus:

    Library API: Exception caught in function 'api_function'
    Backtrace:
    ~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
    ~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
    

    Ja, Erneutes Auslösen von rethrows die ursprüngliche Ausnahme-Objekt, das Sie durch einen Verweis geändert haben. Sie können auch eine Basisklasse Referenz fangen, indem sie sie ändern und noch in der Lage sein, den ursprünglichen abgeleiteten Ausnahmetyp von throw; erneut auslösen.

    für die erste Frage, ja.

    aber für die zweite, beziehen sich auf Vlad Antwort. müssen Sie sorgfältig Ihre Aufgabe Ausnahme Griff Kopie Ctor entwerfen. Vereinbarungsgemäß ist Basisklasse nicht ihr Kind erkennen, so dass Sie werden höchstwahrscheinlich die zusätzlichen Daten, die von abgeleiteten Klasse durch verlieren.

    Lizenziert unter: CC-BY-SA mit Zuschreibung
    Nicht verbunden mit StackOverflow
    scroll top