Ausnahmen mit Message in C++ auslösen

Jay Shaw 12 Oktober 2023
  1. Auslösen von Ausnahmen mit Nachricht unter Verwendung der Standard-C++-Ausnahme – Ungültiges Argument
  2. Auslösen von Ausnahmen mit Nachricht unter Verwendung der standardmäßigen C++-Ausnahme – verschachtelte Ausnahme
  3. Verwenden Sie Runtime Error, um Ausnahmen mit Message in C++ auszulösen
  4. Abschluss
Ausnahmen mit Message in C++ auslösen

In diesem Artikel wird erläutert, wie Ausnahmen mit einer Variablennachricht in C++ ausgelöst werden. Exception throw ist der Vorgang, bei dem die Kontrolle über das Programm verlagert wird, um Abstürze oder Überläufe zu vermeiden.

Es wird ausgeführt, indem ein Ausnahmewurf innerhalb des Programms platziert wird, wo ein Problem auftreten könnte. Es gibt mehrere Schlüsselwörter für die Ausnahmebehandlung in C++, aber dieser Artikel befasst sich mit dem Auslösen von Ausnahmen mit einer variablen Nachricht.

Auslösen von Ausnahmen mit Nachricht unter Verwendung der Standard-C++-Ausnahme – Ungültiges Argument

Dieses Programm verwendet eine ungültiges Argument-Ausnahme von Standardausnahmen von C++, um Ausnahmen mit einer variablen Nachricht auszulösen.

Pakete importieren

Das Programm verwendet zwei Importpakete, stdexcept, um Standard-C++-Ausnahmen einzubinden, und iostream für Eingabe- und Ausgabeoperationen.

Methode zum Auslösen einer Ausnahme

Dieses Programm hat eine Funktion zum Vergleichen zweier als Eingabe bereitgestellter Zahlen definiert und löst einen Ausnahmefall aus, wenn eine negative Eingabe auftritt. Hier wird die Standardausnahme std::invalid_argument verwendet.

In diesem Programm wird eine Methode compare mit zwei ganzzahligen Werten var_a und var_b als Parameter definiert. Dies verwendet if, um nach einer negativen Zahl (a, b oder beides) zu suchen, und löst in diesem Fall eine Ausnahme aus.

if (var_a < 0 || var_b < 0) {
  throw std::invalid_argument("Negative value encountered");

Hauptmethode

Die Methode main verwendet die Ausnahmeschlüsselwörter try-catch, um gültige Ausnahmen auszulösen.

Die Ausnahmebehandlung wird durch Aufrufen der Methode compare innerhalb von try-Blöcken ausgeführt. Da die Eingänge (-1,3) eine negative Zahl haben, sendet der try-Block das Argument an den catch-Block, der Ausnahmen mit einer variablen Nachricht auslöst und die Nachricht ausgibt.

#include <iostream>
#include <stdexcept>

using namespace std;

int check_neg(int var_a, int var_b) {
  if (var_a < 0 || var_b < 0) {
    throw std::invalid_argument("Negative value encountered");
  }
  return 0;
}

int main() {
  try {
    compare(-1, 3);
  } catch (const std::invalid_argument& e) {
    std::cout << "booh!";
  }
}

Ausgang:

booh!
--------------------------------
Process exited after 0.006709 seconds with return value 0
Press any key to continue . . .

Auslösen von Ausnahmen mit Nachricht unter Verwendung der standardmäßigen C++-Ausnahme – verschachtelte Ausnahme

Ausnahmen können miteinander verschachtelt werden, um mehrere Meldungen von Ausnahmeauslösungen nacheinander anzuzeigen. Das Programm in diesem Abschnitt hüllt Fehlermeldungen in verschachtelte Ausnahmen ein, löst dann bei jedem Vorkommen Ausnahmen mit einer variablen Nachricht aus und zeigt sie zusammen an.

Pakete importieren

Die in diesem Programm verwendeten Importpakete sind:

  • iostream
  • stdexcept
  • exception
  • string
  • fstream

Member-Methoden

Das Programm hat drei Member-Funktionen: print_exception, open_file und run.

Methode print_exception:

Es hat zwei öffentliche Parameter – std::exception& ex zum Abfangen von std-Ausnahmen und eine Integer-Variable stage, die mit dem Wert Null initialisiert wird. Innerhalb der Methode wird die erste Zeile std::cerr verwendet, um eine Fehlermeldung zu drucken, die Encountered Exception: lautet, aber sie wird mit std::string(level,'') auf Verschachtelungsebenen platziert.

Auf die Fehlermeldung folgt ex.what, wobei ex ein Objekt von std::exception ist und ex.what eine erklärende Zeichenfolge zu dem aufgetretenen Fehler zurückgibt.

Der try-Block verwendet std::rethrow_if_nested(e), um eine Ausnahme auszulösen, aber nur in dem Fall, in dem das std-Objekt ex von einer verschachtelten Ausnahme abgeleitet wird, was in diesem Programm der Fall ist.

Der catch-Block verwendet ein std-Objekt nestedException, um sich selbst rekursiv erneut aufzurufen, während der Wert von stage um 1 erhöht wird. Die catch(...)-Methode fängt alle Ausnahmen ab.

void print_exception(const std::exception& ex, int level = 0) {
  std::cerr << std::string(level, ' ') << "Encountered Exception: " << ex.what()
            << '\n';
  try {
    std::rethrow_if_nested(ex);
  } catch (const std::exception& nestedException) {
    print_exception(nestedException, stage + 1);
  } catch (...) {
  }
}

Was hier im obigen Code passiert, ist, dass versucht wird, die erklärende Zeichenfolge der Ausnahme auszugeben. Wenn die Funktion sie verschachtelt findet, rekursiv, um die Erklärung der Ausnahme, die sie enthält, auszugeben.

Methode open_file:

Die Funktion hat einen einzigen String-Parameter std::string& s, der ein std::string-Objekt erzeugt und ihm einen Alias s übergibt.

Der try-catch-Block versucht, eine Datei zu lesen, fängt eine Ausnahme ab, wenn die Datei nicht geladen werden kann, und verpackt sie in eine verschachtelte Funktion.

void open_file(const std::string& s) {
  try {
    std::ifstream file(s);
    file.exceptions(std::ios_base::failbit);
  } catch (...) {
    std::throw_with_nested(std::runtime_error("Couldn't open " + s));
  }
}

Methode run():

Die Methode void run() ruft die Methode open_file innerhalb des try-Blocks auf. Der Block catch(...) fängt alle Ausnahmen ab, die durch std::throw_with_nested entstehen.

Es löst eine Ausnahme aus, die e mit der derzeit behandelten Ausnahme kombiniert.

Die gerade behandelte Ausnahme wird zur äußeren Ausnahme und e zur verschachtelten Ausnahme. "run() failed" ist die letzte ausgegebene Meldung.

void run() {
  try {
    open_file("nonexistent.file");
  } catch (...) {
    std::throw_with_nested(std::runtime_error("run() failed"));
  }
}

Methode int main():

Die Methode main ruft die Funktion run() innerhalb des Blocks try auf, während das Programm innerhalb des Blocks catch die Methode print_exception aufruft und dabei e als Parameter übergibt.

Es führt die Funktionen aus, die Ausnahmen mit einer variablen Nachricht auslösen, druckt diese Ausnahmen in einem verschachtelten Format und zeigt eine benutzerdefinierte Nachricht mit jeder Ausnahmeauslösung an.

int main() {
  try {
    run();
  } catch (const std::exception& e) {
    print_exception(e);
  }
}

Vollständiger Code:

#include <exception>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <string>

void print_exception(const std::exception& ex, int stage = 0) {
  std::cerr << std::string(stage, ' ') << "Encountered Exception: " << ex.what()
            << '\n';
  try {
    std::rethrow_if_nested(ex);
  } catch (const std::exception& nestedException) {
    print_exception(nestedException, stage + 1);
  } catch (...) {
  }
}

void open_file(const std::string& s) {
  try {
    std::ifstream file(s);
    file.exceptions(std::ios_base::failbit);
  } catch (...) {
    std::throw_with_nested(std::runtime_error("Couldn't open " + s));
  }
}

void run() {
  try {
    open_file("nonexistent.file");
  } catch (...) {
    std::throw_with_nested(std::runtime_error("run() failed"));
  }
}

int main() {
  try {
    run();
  } catch (const std::exception& e) {
    print_exception(e);
  }
}

Ausgang:

exception: run() failed
 exception: Couldn't open nonexistent.file
  exception: basic_ios::clear

--------------------------------
Process exited after 0.05326 seconds with return value 0
Press any key to continue . . .

Verwenden Sie Runtime Error, um Ausnahmen mit Message in C++ auszulösen

Benutzerdefinierte Klassen können verwendet werden, um Ausnahmen mit einer variablen Nachricht zusammen mit dem Pfad der Quelldatei und der Zeile, in der dieser Fehler ausgegeben wird, auszulösen.

Dieses Programm verwendet benutzerdefinierte Klassen und Makros, um eine variable Nachricht in der erklärenden Zeichenfolge mit std::runtime_error auszugeben.

Pakete importieren

Dieses Programm erfordert vier Importpakete:

#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>

Öffentliche Klasse

Dieses Programm verwendet eine Konstruktorklasse, um Ausnahmen mit einer variablen Nachricht auszulösen und diese benutzerdefinierte Nachricht als erklärende Zeichenfolge anzuzeigen, wenn der öffentliche Konstruktor mit std::runtime_error aufgerufen wird.

Die erste Zeile im Code-Snippet erstellt eine Klasse my_exception und ein neues runtime_error-Objekt. Zusammen mit ihm wird ein String-Objekt msg mit globalem Gültigkeitsbereich erstellt, das verwendet wird, um die erklärende Variable string zu übergeben.

Die Konstruktorklasse my_exception wird mit drei Parametern initialisiert: einem std-String-Objekt arg, das den erklärenden String übergibt, einem Pointer-Objekt *file vom Datentyp char, das den Namen der Datei speichert, und einer Integer-Variablen Zeile, die die Zeile speichert, in der die Ausnahme ausgelöst wird.

Mit std::ostringstream wird ein String-Ausgabeobjekt erstellt, um eine Ausgabe anzuzeigen, wenn dieses Objekt aufgerufen wird. Schließlich wird dieses Objekt in der Variablen msg gespeichert.

Der Destruktor ~my_exception() gibt mit return msg.c_str(); die Variable msg als nullterminierten String zurück.

class my_exception : public std::runtime_error {
  std::string msg;

 public:
  my_exception(const std::string &arg, const char *file, int line)
      : std::runtime_error(arg) {
    std::ostringstream o;
    o << file << ":" << line << ": " << arg;
    msg = o.str();
  }
  ~my_exception() throw() {}
  const char *what() const throw() { return msg.c_str(); }
};

Makros und Exception Throwing

Hier wird ein Makro mit #define throw_line(arg) definiert. Der Aufruf von throw_line() löst my_exception(arg, __FILE__, __LINE__) aus.

Die Methode void f() ruft das Makro throw_line auf und übergibt die Nachricht Oh nein!.

#define throw_line(arg) throw my_exception(arg, __FILE__, __LINE__);

void f() { throw_line("Oh no!"); }

Hauptmethode

Die Hauptmethode löst Ausnahmen mit einer variablen Nachricht aus, indem sie die Methode f() innerhalb des try-Blocks aufruft. Diese übergibt den Meldeblock an die Methode my_exception.

Innerhalb des catch-Blocks wird ein runtime_error-Objekt ex erstellt, das den erklärenden String mit ex.what() aufruft.

Wenn der erklärende String aufgerufen wird, wird das Objekt ostream innerhalb des Konstruktors my_exception aufgerufen und gibt den Dateinamen und die Fehlerzeile zusammen mit der Variablenmeldung zurück.

int main() {
  try {
    f();
  } catch (const std::runtime_error &ex) {
    std::cout << ex.what() << std::endl;
  }
}

Vollständiger Code:

#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>

class my_exception : public std::runtime_error {
  std::string msg;

 public:
  my_exception(const std::string &arg, const char *file, int line)
      : std::runtime_error(arg) {
    std::ostringstream o;
    o << file << ":" << line << ": " << arg;
    msg = o.str();
  }
  ~my_exception() throw() {}
  const char *what() const throw() { return msg.c_str(); }
};
#define throw_line(arg) throw my_exception(arg, __FILE__, __LINE__);

void f() { throw_line("Oh no!"); }

int main() {
  try {
    f();
  } catch (const std::runtime_error &ex) {
    std::cout << ex.what() << std::endl;
  }
}

Ausgang:

D:\c++\std-exceptions\8.cpp:23: Oh no!

--------------------------------
Process exited after 0.006875 seconds with return value 0
Press any key to continue . . .

Abschluss

In diesem Artikel werden die verschiedenen Möglichkeiten erläutert, Ausnahmen mit einer variablen Nachricht auszulösen und dann die Nachricht anzuzeigen, wenn Ausnahmen ausgelöst werden.

Wir hoffen, dass dieser Artikel Ihnen dabei geholfen hat, das Auslösen von Ausnahmen mit einer variablen Nachricht zu lernen, und dass Sie sie in realen Szenarien verwenden können.

Verwandter Artikel - C++ Exception