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
e
  • ehot
  • March 31, 2024, 2:29 p.m.

C++ - Тест 003. Условия и циклы

  • Result:78points,
  • Rating points2
B

C++ - Test 002. Constants

  • Result:16points,
  • Rating points-10
B

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

  • Result:46points,
  • Rating points-6
Last comments
k
kmssrFeb. 8, 2024, 6:43 p.m.
Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVADec. 25, 2023, 10:30 a.m.
Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJoDec. 25, 2023, 8:38 a.m.
Boost - static linking in CMake project under Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
GvozdikDec. 18, 2023, 9:01 p.m.
Qt/C++ - Lesson 056. Connecting the Boost library in Qt for MinGW and MSVC compilers Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Now discuss on the forum
a
a_vlasovApril 14, 2024, 6:41 a.m.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
Павел Дорофеев
Павел ДорофеевApril 14, 2024, 2:35 a.m.
QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
f
fastrexApril 4, 2024, 4:47 a.m.
Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…
AC
Alexandru CodreanuJan. 19, 2024, 11:57 a.m.
QML Обнулить значения SpinBox Доброго времени суток, не могу разобраться с обнулением значение SpinBox находящего в делегате. import QtQuickimport QtQuick.ControlsWindow { width: 640 height: 480 visible: tr…

Follow us in social networks