Evgenii Legotckoi
Evgenii LegotckoiOct. 15, 2017, 5:31 p.m.

C++ - Tutorial 011. Exceptions

What is an exception? This is a situation that is not provided by the standard behavior of the program. For example, an attempt to access an element in the Vector class (which we discussed in the article about classes ), which does not exist. That is, there is a way out of the vector. In this case, you can use exceptions to interrupt the execution of the program. This is necessary because

  • As a rule in such cases, the author of the Vector class does not know how the user wants to use its class, and also does not know in which program this class will be used.
  • A user of the Vector class can not always control the correctness of this class, so he needs to report that something went wrong.

To resolve such a situation in C ++, you can use the exception technique.


Consider how to write an exception call when an element is attempted to access an element that does not exist in the Vector class.

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

Here, the out_of_range exception is used. This exception is defined in the header file.

The throw statement passes control to the handler for out_of_range exceptions in some function that directly or indirectly calls Vector::operator . In order to handle exceptions, you must use the try catch statement block.

void f(Vector& v)
{
    // ...
    try { // function block with exception
        v[v.size()] = 7; // attempt to access an element outside the vector
    }
    catch (out_of_range) { // catch the error out_of_range
        // ... error handling out_of_range ...
    }
    // ...
}

Invariants

Also, try catch blocks allow processing of several different exceptions, which introduces invariance into the operation of the C ++ exception mechanism....

For example, a vector class can create an invalid vector size when it is created, or it can not find free memory for the elements it will contain.

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

This constructor can throw an exception in two cases:

  • If a negative value is passed as the size argument
  • If the operator new can not allocate memory

length_error - This is the standard exception operator, because the std library often uses exception data in its work.

Exception handling will look like this:

void test()
{
    try {
        Vector v(−27);
    }
    catch (std::length_error) {
        // processing of negative vector size
    }
    catch (std::bad_alloc) {
        // memory allocation error handling
    }
}

You can also create your own exceptions.

Types of Exceptions

All exceptions to the standard library are inherited from std::exception.

At the moment, there are the following types of exceptions:

  • logic_error
  • invalid_argument
  • domain_error
  • length_error
  • out_of_range
  • future_error (C++11)
  • runtime_error
  • range_error
  • overflow_error
  • underflow_error
  • system_error (C++11)
  • ios_base::failure (начиная с C++11)
  • bad_typeid
  • bad_cast
  • bad_weak_ptr (C++11)
  • bad_function_call (C++11)
  • bad_alloc
  • bad_array_new_length (C++11)
  • bad_exception
  • ios_base::failure (до C++11)

std::logic_error

An exception is defined in the header file

Defines the type of object that will be thrown as an exception. He reports errors that are the result of incorrect logic within the program, such as a violation of a logical prerequisite or a class of invariants that can be prevented.

This class is used as the basis for errors that can only be determined at run-time.

std::invalid_argument

An exception is defined in the header file

Inherited from std::logic_error. Defines an exception that must be thrown in case of an incorrect argument.

For example, MSDN gives an example when an object of the bitset class from the standard library

// 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 this example, an incorrect string is passed, inside of which there is a character 'b', which will be erroneous.

std::domain_error

An exception is defined in the header file

Inherited from std::logic_error. Defines an exception that must be thrown if the mathematical function is not defined for the argument that is passed to it, for example:

std::sqrt(-1)

std::length_error

An exception is defined in the header file

Inherited from std::logic_error. Specifies the exception that must be given to the brochete when an attempt is made to implement an excess of the allowed limits for the object. As was shown for the vector size at the beginning of theи.

std::out_of_range

An exception is defined in the header file

Inherited from std::logic_error. Defines an exception that must be thrown when it is outside the allowed range of object values. As it was shown for the range of values of the wind at the beginning of the article.

std::future_error

An exception is defined in the header file

Inherited from std::logic_error. This exception can be thrown in the event that the function that operates in asynchronous mode and depends on the thread library failed. This exception has an error code that is compatible with std::error_code.

std::runtime_error

An exception is defined in the header file

This is the basic exception for exceptions that can not be easily predicted and must be thrown during program execution.

std::range_error

An exception is defined in the header file

The exception is used for errors when computing floating-point values when the computer can not process the value, because it is either too large or too small. If the value is an integral type, then underflow_error or overflow_error should be used.

std::overflow_error

An exception is defined in the header file

The exception is used for errors in the calculation of floating point values of the integral type, when the number is too large a positive value.

std::underflow_error

An exception is defined in the header file

The exception is used for errors when calculating floating point values of an integral type when the number is too large a negative value.

std::system_error

An exception is defined in the header file

std::system_error is an exception type that is called by various functions of the standard library (usually functions that interact with the operating system, for example, the std::thread constructor), with the exception having the corresponding std::error_code .

std::ios_base::failure

An exception is defined in the header file

It is responsible for exceptions that are thrown when I / O functions fail.

std::bad_typeid

An exception is defined in the header file

An exception of this type occurs when the typeid operator is applied to a null pointer of a polymorphic type.

#include <iostream>
#include <typeinfo>

struct S { // The type must be polymorphic
    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

An exception is defined in the header file

This exception occurs when an object cast is attempted in that type of object that does not include inheritance relations with it.

#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

An exception is defined in the header file

std::bad_weak_ptr - the type of the object, generated as an exception by the constructors std::shared_ptr, which accept std::weak_ptr as an argument when std::weak_ptr refers to an already deleted object.

#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

An exception is defined in the header file

This exception is generated if the std::function() method of the std::function object was called, which did not receive the function object, that is, it was passed as the initializer nullptr, for example, and the function object was not was transferred.

#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

An exception is defined in the header file

Called when the memory can not be allocated.

std::bad_array_new_length

An exception is defined in the header file

An exception is thrown in the following cases:

  1. The array has a negative size
  2. The total size of the new array exceeded the maximum value determined by the implementation
  3. The number of initialization elements exceeds the suggested number of initializers
#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

An exception is defined in the header file

std::bad_exception - This is an exception type in C ++ that is executed in the following situations:

  1. If the dynamic exception specification is violated
  2. If std::exception_ptr stores a copy of the caught exception, and if the copy constructor of the exception object caught the current_exception, then an exception is thrown for exceptions.
#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';
    }
}
We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

P
  • Oct. 15, 2017, 11 p.m.

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

Evgenii Legotckoi
  • Oct. 16, 2017, 2:46 a.m.

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

Comments

Only authorized users can post comments.
Please, Log in or Sign up
L
  • Leo
  • Sept. 26, 2023, 11:43 a.m.

C++ - Test 002. Constants

  • Result:41points,
  • Rating points-8
L
  • Leo
  • Sept. 26, 2023, 11:32 a.m.

C++ - Test 001. The first program and data types

  • Result:93points,
  • Rating points8
Last comments
IscanderChe
IscanderCheSept. 13, 2023, 9:11 a.m.
QScintilla C++ example По горячим следам (с другого форума вопрос задали, пришлось в памяти освежить всё) решил дополнить. Качаем исходники с https://riverbankcomputing.com/software/qscintilla/downlo…
Evgenii Legotckoi
Evgenii LegotckoiSept. 6, 2023, 7:18 a.m.
Qt/C++ - Lesson 048. QThread — How to work with threads using moveToThread Разве могут взаимодействовать объекты из разных нитей как-то, кроме как через сигнал-слоты?" Могут. Выполняя оператор new , Вы выделяете под объект память в куче (heap), …
AC
Andrei CherniaevSept. 5, 2023, 3:37 a.m.
Qt/C++ - Lesson 048. QThread — How to work with threads using moveToThread Я поясню свой вопрос. Выше я писал "Почему же в методе MainWindow::on_write_1_clicked() Можно обращаться к методам exampleObject_1? Разве могут взаимодействовать объекты из разных…
n
nvnAug. 31, 2023, 9:47 a.m.
QML - Lesson 004. Signals and Slots in Qt QML Здравствуйте! Прекрасный сайт, отличные статьи. Не хватает только готовых проектов для скачивания. Многих комментариев типа appCore != AppCore просто бы не было )))
NSProject
NSProjectAug. 24, 2023, 1:40 p.m.
Django - Tutorial 023. Like Dislike system using GenericForeignKey Ваша ошибка связана с gettext from django.utils.translation import gettext_lazy as _ Поле должно выглядеть так vote = models.SmallIntegerField(verbose_name=_("Голос"), choices=VOTES) …
Now discuss on the forum
IscanderChe
IscanderCheSept. 17, 2023, 9:24 a.m.
Интернационализация строк в QMessageBox Странная картина... Сделал минимально работающий пример - всё работает. Попробую на другой операционке. Может, дело в этом.
NSProject
NSProjectSept. 17, 2023, 8:49 a.m.
Помогите добавить Ajax в проект В принципе ничего сложного с отправкой на сервер нет. Всё что ты хочешь отобразить на странице передаётся в шаблон и рендерится. Ты просто создаёшь файл forms.py в нём описываешь свою форму и в …
BlinCT
BlinCTSept. 15, 2023, 12:35 p.m.
Размеры полей в TreeView Всем привет. Пытаюсь сделать дерево вот такого вида Пытаюсь организовать делегат для каждой строки в дереве. ТО есть отступ какого то размера и если при открытии есть под…
IscanderChe
IscanderCheSept. 8, 2023, 12:07 p.m.
Кастомная QAbstractListModel и цвет фона, цвет текста и шрифт Похоже надо не абстрактный , а "реальный" типа QSqlTableModel Да, но не совсем. Решилось с помощью стайлшитов и setFont. Спасибо за отлик!
Evgenii Legotckoi
Evgenii LegotckoiSept. 6, 2023, 6:35 a.m.
Вопрос: Нужно ли в деструкторе удалять динамически созданные QT-объекты. Напр: Зависит от того, как эти объекты были созданы. Если вы передаёте указатель на parent объект, то не нужно, Ядро Qt само разрулит удаление, если нет, то нужно удалять вручную, иначе будет ут…

Follow us in social networks