При выполнении кода на C++ могут возникать разные ошибки, которые не позволяют программе выполнять свою работу. Для работы с ошибками или исключениями в C++ используются ключевые слова try , catch и throw.
Содержание статьи:
1. Вступление: виды исключений и знакомство с try, catch и throw в C++
2. Генерируем исключения в C++
4. Обрабатываем ошибки с try и catch in С++
5. Как работают throw, try и catch в C++: примеры
6. Еще немного о порядке обработке ошибок в C++
Есть два вида исключений, с которыми вы можете столкнуться в процессе:
Когда происходит какое-то событие, прерывающее нормальное функционирование программы, C ++ обычно останавливается и выдает сообщение об ошибке. Когда это происходит, говорят, что C++ выбрасывает ошибку — throw an exception. Мы уже упоминали, что для работы с ошибками или исключениями в C++ используются определенные ключевые слова, давайте познакомимся с ними поближе:
try: позволяет определить блок кода, который будет проверяться на наличие ошибок во время его выполнения;throw: нужен для создания и отображения исключений и используется для перечисления ошибок, которые генерирует функция, но не может самостоятельно обрабатывать исключения;catch— блок кода, который выполняется при возникновении определенного исключения в блоке try.Давайте посмотрим, как выглядит пример кода в С++ с использованием try catch и throw:
try {
int age = 15;
if (age >= 18) {
cout << "Access granted - you are old enough.";
} else {
throw (age);
}
}
catch (int myNum) {
cout << "Access denied - You must be at least 18 years old.\n";
cout << "Age is: " << myNum;
}
Вкратце объясним, как работают операторы try и catch в С++ на примере этого блока. Мы используем блок try для тестирования определенных строк кода: если переменная age меньше 18, мы генерируем исключение и обрабатываем его в блоке catch.
С помощью catch мы перехватываем ошибку и прописываем способ ее обработки. Оператор принимает параметр: в примере используется переменная типа int myNum для вывода значения возраста.
Если все данные соответствуют установленным параметрам, то ошибки не возникает. Например, если указанный возраст будет больше 18, а не 15, как указано в примере, то блок catch просто пропускается.
Если ошибка присутствует, то оператор throw выбросит ошибку. В throw можно прописать любое значение и оператор может выдать текст с пояснением, например:
Access denied - You must be at least 18 years old. Age is: 15
Или установить числовое значение, например, то код ошибки будет выглядеть следующим образом:
Access denied - You must be at least 18 years old. Error number: 505
После такой большой вводной части подробно рассмотрим генерацию исключений и как их обрабатывать, примеры использования try и catch в С++, подробно расскажем про задачи операторов.
Исключения могут быть выброшены в любом месте кода. Для этого в блоке нужно прописать throw.
Этот оператор определяет тип исключения и может быть любым выражением. Также throw сигнализирует об ошибке в коде и выводит исключение в консоль.
Помимо использования оператора throw, есть еще один способ мониторить ошибки в коде. Он более традиционный, но давайте рассмотрим и его, чтобы лучше понять механику обработки ошибок с помощью операторов.
Обычно мы разбиваем программу на несколько функций или подпрограмм, чтобы сделать ее читабельной и простой для понимания. Получается, что программа будет иметь связанные вызовы функций. То есть одна функция использует ту информацию, которую ей предоставляет другая функция.
Здесь возникают основные проблемы с обработкой ошибок при использовании оператора if:
Вот так выглядит обработка ошибок в коде при использовании оператора if:
unsigned int error_type = 0;
int add(int a, int b)
{
if (a > 100 || b > 100)
{
error_type = 1;
return -1;
}
else if (a < 0 || b < 0)
{
error_type = 2;
return -1;
}
return a + b;
}
int add_wrapper(int a, int b)
{
return add(a, b);
}
int main(int, char**)
{
if (add_wrapper(-1, 8) < 0)
{
if (error_type == 1)
{
std::cout << "add operation failed. parameters must be <= 100" << "\n";
}
else
{
std::cout << "add operation failed. parameters must be >= 0" << "\n";
}
}
else
{
std::cout << "add operation succeeded" << "\n";
}
return 0;
}
А вот так будет выглядеть код с использованием try и catch в С++ (example):
#include <iostream>
using namespace std;
class Test {
public:
Test() { cout << "Constructor of Test " << endl; }
~Test() { cout << "Destructor of Test " << endl; }
};
int main()
{
try {
Test t1;
throw 10;
}
catch (int i) {
cout << "Caught " << i << endl;
}
}
По сравнению с несколькими строками кода в случае try и catch в С++, предыдущий блок выглядит очень перегруженным и длинным. В целом при использовании оператора if обработка ошибок и программный код тесно взаимосвязаны. Из-за этого код становится беспорядочным, и трудно гарантировать, что все ошибки будут обработаны и программа будет работать нормально.
Метод try/catch, в свою очередь, обеспечивает четкое разделение между кодом, который знает об ошибке, и кодом, который знает, как обрабатывать ошибку. Таким образом, код, который находятся между этими операторами, может безопасно игнорировать ошибку.
Поэтому, запуская код в С++ Builder, лучше искать исключения с помощью try, catch и throw. Это сделает ваш код проще, чище и с меньшей вероятностью вы допустите ошибки в программе.
Для того чтобы проверить блок кода на ошибки и аномалии, используется оператор try. Так мы можем быть уверены, что если появится исключение в этой части кода, то try его заметит. Главная особенность оператора в том, что в отличие от if / else, которые смешиваются с обычным потоком данных, try отделяет обработку ошибок от обычного течения программы.
Блок try помещается вокруг кода, который может генерировать исключение, и закрывается другим оператором этой пары — catch. Код в блоке try / catch называется защищенным кодом, а синтаксис для использования связки этих операторов выглядит следующим образом:
try {
// protected code
} catch( ExceptionName e1 ) {
// catch block
} catch( ExceptionName e2 ) {
// catch block
} catch( ExceptionName eN ) {
// catch block
}
С помощью метода try / catch можно перечислить и поймать сразу несколько видов исключений, если блок try вызывает несколько типов ошибок в разных ситуациях. Несмотря на то, что функция может генерировать множество исключений, вы можете обрабатывать не все, а только некоторые из них.
Блок catch, идущий в паре с оператором try, ловит и обрабатывает исключения. Чтобы указать, какой тип исключения вы хотите поймать и обработать, нужно прописать это в скобках после ключевого слова catch:
try {
// protected code
} catch( ExceptionName e ) {
// code to handle ExceptionName exception
}
Приведенный выше код перехватит только исключение типа ExceptionName. Если вы хотите указать, что блок catch должен обрабатывать любой тип ошибок, который находит оператор try, просто поместите многоточие ... между скобками:
try {
// protected code
} catch(...) {
// code to handle any exception
}
Рассмотрим пример кода, в котором генерируется исключение деления на ноль:
#include <iostream>
using namespace std;
double division(int a, int b) {
if( b == 0 ) {
throw "Division by zero condition!";
}
return (a/b);
}
int main () {
int x = 50;
int y = 0;
double z = 0;
try {
z = division(x, y);
cout << z << endl;
} catch (const char* msg) {
cerr << msg << endl;
}
return 0;
}
Так как программа вызывает тип исключения const char *, в блоке catch необходимо указать const char *, чтобы ошибку можно было определить и обработать. Если скомпилировать и запустить этот блок кода, то в результате получим условие прописанное в throw:
Division by zero condition!
Рассмотрим на примерах, как между собой взаимодействуют операторы throw, try и catch в С++. В блоке кода ниже приведен простой пример, демонстрирующий обработку исключений. Результат программы наглядно покажет, в какой последовательности происходит выполнение операторов:
#include <iostream>
using namespace std;
int main()
{
int x = -1;
// Some code
cout << "Before try \n";
try {
cout << "Inside try \n";
if (x < 0)
{
throw x;
cout << "After throw (Never executed) \n";
}
}
catch (int x ) {
cout << "Exception Caught \n";
}
cout << "After catch (Will be executed) \n";
return 0;
}
В результате получается следующая последовательность:
Before try Inside try Exception Caught After catch (Will be executed)
Нужно не забывать прописывать одинаковые типы исключений в try / catch. Если исключение одного типа будет выброшено, а catch не сможет его поймать и обработать, то программа завершается ненормально:
#include <iostream>
using namespace std;
int main()
{
try {
throw 'a';
}
catch (int x) {
cout << "Caught ";
}
return 0;
}
В этом примере кода исключение является символом, но блок catch для захвата символа отсутствует. В результате блок вернет нам не исключение, а вот такое предупреждение:
terminate called after throwing an instance of 'char' This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information.
С помощью try / catch можно указывать кастомные типы исключений, наследуя и переопределяя функциональность класса исключений. В примере ниже приведем код, который покажет, как вы можете использовать класс std :: exception для генерации собственной ошибки стандартным способом:
#include <iostream>
#include <exception>
using namespace std;
struct MyException : public exception {
const char * what () const throw () {
return "C++ Exception";
}
};
int main() {
try {
throw MyException();
} catch(MyException& e) {
std::cout << "MyException caught" << std::endl;
std::cout << e.what() << std::endl;
} catch(std::exception& e) {
//Other errors
}
}
Результат выполнения кода выглядит так:
MyException caught C++ Exception
Когда мы прописываем операторы try / catch в коде, то исключение выбрасывается только при исполнении определенных условий. Рассмотрим как работают try, catch и throw в С++ на примере:
#include <cmath> // for sqrt() function
#include <iostream>
int main()
{
std::cout << "Enter a number: ";
double x {};
std::cin >> x;
try // Ищет исключения в блоке и направляет их к обработчику catch
{
// этот блок сработает, если пользователь ввел отрицательное число
if (x < 0.0)
throw "Can not take sqrt of negative number"; // throw выбрасывает исключение типа const char*
// Если пользователь ввел число больше 0, то выполняется этот блок кода
std::cout << "The sqrt of " << x << " is " << std::sqrt(x) << '\n';
}
catch (const char* exception) // обработчик исключений типа const char*
{
std::cerr << "Error: " << exception << '\n';
}
}
Пользователь может ввести число больше нуля, как и задумано. Тогда программа просто продолжит работать в нормальном режиме и пропустит блок с оператором catch. Допустим, пользователь ввел число 49. Тогда результат выполнения кода будет следующим:
Enter a number: 49 The sqrt of 49 is 7
Но пользователи не всегда действуют так, как задумывал разработчик. Поэтому оператор catch нужен нам для того, чтобы программа не сломалась от непредвиденных значений, а могла нормально функционировать и дальше. Поэтому если пользователь введет число меньше нуля, то после того, как try обнаружит непредусмотренное значение, заработают операторы catch и throw, и программа выдаст такое значение:
Enter a number: -4 Error: Can not take sqrt of negative number
Таким образом, строки кода с catch и throw выполняются только тогда, когда try обнаруживает исключение в коде. Если все данные удовлетворяют условиям кода, то блок с исключениями просто пропускается программой.
Как использовать try, catch и throw в С++, мы разобрались. Теперь кратко напомним, зачем все это нужно:
try / catch занимает меньше строк и легче читается. Блоков с операторами if / else может быть очень много и они будут повторяться, тогда как try / catch содержит только два блока. Видео: С++ try catch. Обработка исключений С++. Try catch: что это. Изучение С++ для начинающих
На фоне роста спроса на ликвидность в бычьем рынке 2025 года, криптозаймы снова выходят на…
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…
Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…
В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…
Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…