Evgenii Legotckoi
Evgenii Legotckoi15. Oktober 2017 17:31

C++ - Tutorial 011. Ausnahmen

Was ist eine Ausnahme? Dies ist eine Situation, die durch das Standardverhalten des Programms nicht vorgesehen ist. Versuchen Sie beispielsweise, auf ein Element in der Vector-Klasse zuzugreifen (das wir im Artikel classes besprochen haben), das nicht existiert. Das heißt, der Vektor ist außerhalb der Grenzen. In diesem Fall können Sie Ausnahmen verwenden, um die Programmausführung zu unterbrechen. Dies ist notwendig, weil

  • In solchen Fällen weiß der Autor der Vector -Klasse in der Regel nicht, wie der Benutzer seine Klasse verwenden möchte, und weiß auch nicht, in welchem Programm diese Klasse verwendet wird.
  • Der Benutzer der Vector -Klasse kann nicht immer den korrekten Betrieb dieser Klasse kontrollieren, also muss er informiert werden, dass etwas schief gelaufen ist.

Um solche Situationen in C++ zu lösen, können Sie die Technik der Ausnahmen verwenden.


Betrachten wir, wie eine Ausnahme geschrieben wird, wenn versucht wird, auf ein Element über einen Index zuzugreifen, der in der Vector-Klasse nicht vorhanden ist.

double& Vector::operator[](int i)
{
    if (i<0 || size()<=i) throw out_of_range{"Vector::operator[]"};
    return elem[i];
}

Hier gilt die Ausnahme out_of_range. Diese Ausnahme ist in der Header-Datei definiert .

Der Operator throw übergibt die Steuerung an einen Ausnahmehandler vom Typ out_of_range in einer Funktion, die direkt oder indirekt Vector::operator aufruft. Um Ausnahmen zu behandeln, müssen Sie den Anweisungsblock try catch. verwenden.

void f(Vector& v)
{
    // ...
    try { // блок обработки функции с исключением
        v[v.size()] = 7; // попытка доступа к элементу за пределами вектора
    }
    catch (out_of_range) { // ловим ошибку out_of_range 
        // ... обработки ошибки out_of_range ...
    }
    // ...
}

Invariante

Außerdem ermöglichen Ihnen try catch -Blöcke, mehrere verschiedene Ausnahmen zu behandeln, wodurch Invarianz in den Betrieb des C++-Ausnahmemechanismus eingeführt wird.

Beispielsweise kann die Vektorklasse, wenn sie erstellt wird, die falsche Größe des Vektors erhalten oder keinen freien Speicher für die Elemente finden, die sie enthalten wird.

Vector::Vector(int s)
{
    if (s < 0) throw length_error{};
    elem = new double[s];
    sz = s;
}

Dieser Konstruktor kann in zwei Fällen eine Ausnahme auslösen:

  • Wenn als Größe -Argument ein negativer Wert übergeben wird
  • Wenn der Operator new keinen Speicher zuweist

length_error ist der Standardoperator für Ausnahmen, da die std-Bibliothek diese Ausnahmen häufig in ihrer Arbeit verwendet.

Die Ausnahmebehandlung sieht folgendermaßen aus:

void test()
{
    try {
        Vector v(−27);
    }
    catch (std::length_error) {
        // обработка отрицательного размера вектора
    }
    catch (std::bad_alloc) {
        // обработка ошибки выделения памяти
    }
}

Sie können auch Ihre eigenen Ausnahmen hervorheben.

Arten von Ausnahmen

Alle Ausnahmen der Standardbibliothek erben von std::exception.

Derzeit gibt es folgende Arten von Ausnahmen:

  • Logikfehler
  • ungültiges_argument
  • Domänenfehler
  • Längenfehler
  • außer Reichweite
  • future_error (C++11)
  • Laufzeit Fehler
  • range_error
  • overflow_error
  • Unterlauffehler
  • system_error (C++11)
  • ios_base::failure (seit C++11)
  • bad_typeid
  • bad_cast
  • bad_weak_ptr (C++11)
  • bad_function_call (C++11)
  • bad_alloc
  • bad_array_new_length (C++11)
  • schlechte_Ausnahme
  • ios_base::failure (vor C++11)

std::logic_error

Ausnahme in Header-Datei definiert

Gibt den Objekttyp an, der als Ausnahme ausgelöst werden soll. Es meldet Fehler, die das Ergebnis einer falschen Logik innerhalb des Programms sind, wie z. B. eine Verletzung einer logischen Prämisse oder einer Klasse von Invarianten, die verhindert werden kann.

Diese Klasse dient als Grundlage für Fehler, die erst zur Laufzeit erkannt werden können.

std::invalid_argument

Ausnahme in Header-Datei definiert

Geerbt von std::logic_error. Definiert eine Ausnahme, die im Falle eines ungültigen Arguments ausgelöst wird.

Beispielsweise gibt MSDN ein Beispiel für ein Objekt der Bitset-Klasse aus der Standardbibliothek

// invalid_arg.cpp  
// compile with: /EHsc /GR  
#include <bitset>  
#include <iostream>  

using namespace std;  

int main( )  
{  
   try   
   {  
      bitset< 32 > bitset( string( "11001010101100001b100101010110000") );  
   }  
   catch ( exception &e )   
   {  
      cerr << "Caught " << e.what( ) << endl;  
      cerr << "Type " << typeid( e ).name( ) << endl;  
   };  
}  
\* Output:   
Caught invalid bitset<N> char  
Type class std::invalid_argument  
*\ 

In diesem Beispiel wird eine ungültige Zeichenfolge übergeben, in der sich ein fehlerhaftes Zeichen „b“ befindet.

std::domain_error

Ausnahme in Header-Datei definiert

Geerbt von std::logic_error. Gibt eine Ausnahme an, die ausgelöst wird, wenn eine mathematische Funktion für das angegebene Argument nicht definiert ist, zum Beispiel:

std::sqrt(-1)

std::length_error

Ausnahme in Header-Datei definiert

Geerbt von std::logic_error. Gibt die Ausnahme an, die ausgelöst werden soll, wenn versucht wird, ein Out-of-Bounds für ein Objekt zu implementieren. Wie für die Größe des Vektors am Anfang des Artikels gezeigt.

std::out_of_range

Ausnahme in Header-Datei definiert

Geerbt von std::logic_error. Gibt die Ausnahme an, die ausgelöst werden soll, wenn der Wertebereich eines Objekts außerhalb der Grenzen liegt. Wie es für den Wertebereich des Vektors am Anfang des Artikels gezeigt wurde.

std::future_error

Ausnahme in Header-Datei definiert

Geerbt von std::logic_error. Diese Ausnahme kann ausgelöst werden, wenn eine Funktion, die im asynchronen Modus arbeitet und von der Threadbibliothek abhängt, nicht ausgeführt werden konnte. Diese Ausnahme trägt einen Fehlercode, der mit std::error_code kompatibel ist.

std::runtime_error

Ausnahme in Header-Datei definiert

Ist die Basisausnahme für Ausnahmen, die nicht einfach vorhergesagt werden können und zur Laufzeit ausgelöst werden müssen.

std::range_error

Ausnahme in Header-Datei definiert

Eine Ausnahme gilt für Fehler bei der Berechnung von Fließkommawerten, wenn der Computer den Wert nicht verarbeiten kann, weil er entweder zu groß oder zu klein ist. Wenn der Wert ein ganzzahliger Wert ist, müssen die Ausnahmen underflow_error oder overflow_error verwendet werden.

std::overflow_error

Ausnahme in Header-Datei definiert

Eine Ausnahme wird für Fehler bei der Berechnung von Gleitkommawerten vom ganzzahligen Typ verwendet, wenn die Zahl einen zu großen positiven Wert hat, positiv unendlich, bei dem es zu einem Genauigkeitsverlust kommt, d.h. das Ergebnis ist so groß, dass es nicht als IEEE754-Zahl dargestellt werden kann.

std::underflow_error

Ausnahme in Header-Datei definiert

Die Ausnahme wird für Fehler bei der Berechnung von Gleitkommawerten vom ganzzahligen Typ verwendet, bei denen es zu einem Genauigkeitsverlust kommt, d.h. das Ergebnis ist so klein, dass es nicht als IEEE754-Nummer dargestellt werden kann.

std::system_error

Ausnahme in Header-Datei definiert

std::system_error ist eine Art von Ausnahme, die von verschiedenen Standardbibliotheksfunktionen ausgelöst wird (normalerweise Funktionen, die mit dem Betriebssystem interagieren, wie z. B. der std::thread -Konstruktor), wobei die Ausnahme eine hat entsprechende * std::error_code * .

std::ios_base::failure

Ausnahme in Header-Datei definiert

Verantwortlich für Ausnahmen, die ausgelöst werden, wenn E/A-Funktionen fehlschlagen.

std::bad_typeid

Ausnahme in Header-Datei definiert

Eine Ausnahme dieses Typs wird ausgelöst, wenn der typeid -Operator auf einen Nullzeiger eines polymorphen Typs angewendet wird.

#include <iostream>
#include <typeinfo>

struct S { // Тип должен быть полиморфным
    virtual void f();
}; 

int main()
{
    S* p = nullptr;
    try {
        std::cout << typeid(*p).name() << '\n';
    } catch(const std::bad_typeid& e) {
        std::cout << e.what() << '\n';
    }
}

std::bad_cast

Ausnahme in Header-Datei definiert

Diese Ausnahme tritt auf, wenn versucht wird, ein Objekt in einen Objekttyp umzuwandeln, der keine Vererbungsbeziehung zu ihm hat.

#include <iostream>
#include <typeinfo>

struct Foo { virtual ~Foo() {} };
struct Bar { virtual ~Bar() {} };

int main()
{
    Bar b;
    try {
        Foo& f = dynamic_cast<Foo&>(b);
    } catch(const std::bad_cast& e)
    {
        std::cout << e.what() << '\n';
    }
}

std::bad_weak_ptr

Ausnahme in Header-Datei definiert

std::bad_weak_ptr ist der Objekttyp, der als Ausnahme von std::shared_ptr -Konstruktoren ausgelöst wird, die std::weak_ptr als Argument nehmen, wenn std::weak_ptr darauf verweist ein bereits gelöschtes Objekt.

#include <memory>
#include <iostream>
int main()
{
    std::shared_ptr<int> p1(new int(42));
    std::weak_ptr<int> wp(p1);
    p1.reset();
    try {
        std::shared_ptr<int> p2(wp);
    } catch(const std::bad_weak_ptr& e) {
        std::cout << e.what() << '\n';
    }
}

std::bad_function_call

Ausnahme in Header-Datei definiert

Diese Ausnahme wird ausgelöst, wenn die std::function::operator() -Methode des std::function -Objekts aufgerufen wurde und kein Funktionsobjekt erhalten hat, d. h. es wurde nullptr als an übergeben initializer, und das Funktionsobjekt wurde nie übergeben.

#include <iostream>
#include <functional>

int main()
{
    std::function<int()> f = nullptr;
    try {
        f();
    } catch(const std::bad_function_call& e) {
        std::cout << e.what() << '\n';
    }
}

std::bad_alloc

Ausnahme in Header-Datei definiert

Wird aufgerufen, wenn kein Arbeitsspeicher zugewiesen werden kann.

std::bad_array_new_length

Ausnahme in Header-Datei definiert

In den folgenden Fällen wird eine Ausnahme ausgelöst:

  1. Das Array hat eine negative Größe
  2. Die Gesamtgröße des neuen Arrays hat den von der Implementierung definierten Maximalwert überschritten
  3. Die Anzahl der Initialisierungselemente überschreitet die vorgeschlagene Anzahl der Initialisierungselemente
#include <iostream>
#include <new>
#include <climits>

int main()
{
    int negative = -1;
    int small = 1;
    int large = INT_MAX;
    try {
        new int[negative];           // negative size
        new int[small]{1,2,3};       // too many initializers
        new int[large][1000000];     // too large
    } catch(const std::bad_array_new_length &e) {
        std::cout << e.what() << '\n';
    }
}

std::bad_exception

Ausnahme in Header-Datei definiert

std::bad_exception ist eine Art C++-Ausnahme, die in den folgenden Situationen ausgelöst wird:

  1. Wenn die dynamische Ausnahmespezifikation verletzt wird
  2. Wenn std::exception_ptr eine Kopie der abgefangenen Ausnahme enthält und wenn der Kopierkonstruktor des Ausnahmeobjekts die aktuelle_Ausnahme abgefangen hat, dann wird eine abgefangene Ausnahme ausgelöst.
#include <iostream>
#include <exception>
#include <stdexcept>

void my_unexp() { throw; }

void test() throw(std::bad_exception)
{
    throw std::runtime_error("test");
}

int main()
{
    std::set_unexpected(my_unexp);
    try {
         test();
    } catch(const std::bad_exception& e)
    {
        std::cerr << "Caught " << e.what() << '\n';
    }
}
Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

P
  • 15. Oktober 2017 23:00

std::underflow_error - это не "число имеет слишком большое отрицательное значение", а потеря точности при вычислениях, т.е. результат настолько мал, что не может быть представлен числом в формате IEEE754

Evgenii Legotckoi
  • 16. Oktober 2017 02:46

Спасибо. Дополнил.

Kommentare

Nur autorisierte Benutzer können Kommentare posten.
Bitte Anmelden oder Registrieren
Letzte Kommentare
A
ALO1ZE19. Oktober 2024 08:19
Fb3-Dateileser auf Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов5. Oktober 2024 07:51
Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55. Juli 2024 11:02
QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr8. Februar 2024 18:43
Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Jetzt im Forum diskutieren
J
JacobFib17. Oktober 2024 03:27
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
JW
Jhon Wick1. Oktober 2024 15:52
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл Гусарев27. September 2024 09:09
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
Fynjy22. Juli 2024 04:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Folgen Sie uns in sozialen Netzwerken