Как выбросить исключение С++

У меня очень плохое понимание обработки исключений (т.е. как настроить команды throw, try, catch для моих собственных целей).

Например, я определил функцию следующим образом: int compare(int a, int b){...}

Я хочу, чтобы функция выдавала исключение с некоторым сообщением, когда либо a, либо b отрицательно.

Как мне подойти к этому в определении функции?

Ответ 1

Простой:

#include <stdexcept>

int compare( int a, int b ) {
    if ( a < 0 || b < 0 ) {
        throw std::invalid_argument( "received negative value" );
    }
}

Стандартная библиотека поставляется с хорошей коллекцией встроенных объектов исключений, которые вы можете бросить. Имейте в виду, что вы всегда должны бросать по значению и ловить по ссылке:

try {
    compare( -1, 3 );
}
catch( const std::invalid_argument& e ) {
    // do stuff with exception... 
}

У вас может быть несколько операторов catch() после каждой попытки, поэтому вы можете обрабатывать разные типы исключений отдельно, если хотите.

Вы также можете повторно выбрасывать исключения:

catch( const std::invalid_argument& e ) {
    // do something

    // let someone higher up the call stack handle it if they want
    throw;
}

И для исключения исключений, независимо от типа:

catch( ... ) { };

Ответ 2

Просто добавьте throw, где необходимо, и try заблокируйте вызывающего, который обрабатывает ошибку. По соглашению вы должны только бросать вещи, которые происходят из std::exception, поэтому сначала включите <stdexcept>.

int compare(int a, int b) {
    if (a < 0 || b < 0) {
        throw std::invalid_argument("a or b negative");
    }
}

void foo() {
    try {
        compare(-1, 0);
    } catch (const std::invalid_argument& e) {
        // ...
    }
}

Кроме того, просмотрите Boost.Exception.

Ответ 3

Вы можете определить сообщение для броска при возникновении определенной ошибки:

throw std::invalid_argument( "received negative value" );

или вы можете определить его следующим образом:

std::runtime_error greatScott("Great Scott!");          
double getEnergySync(int year) {                        
    if (year == 1955 || year == 1885) throw greatScott; 
    return 1.21e9;                                      
}                                                       

Как правило, у вас будет блок try ... catch следующим образом:

try {
// do something that causes an exception
}catch (std::exception& e){ std::cerr << "exception: " << e.what() << std::endl; }

Ответ 4

Хотя этот вопрос довольно старый и уже был дан ответ, я просто хочу добавить примечание о том, как выполнять правильную обработку исключений в С++ 11:

Используйте std::nested_exception и std::throw_with_nested

Ниже описано, как здесь и здесь, как вы можете получить обратную трассировку на ваши исключения внутри вашего кода, не требуя отладчика или громоздкого ведения журнала, просто написав правильный обработчик исключений, который ревертирует вложенные исключения.

Поскольку вы можете сделать это с помощью любого производного класса исключения, вы можете добавить много информации в такую ​​обратную линию! Вы также можете взглянуть на мой MWE на GitHub, где обратная сторона будет выглядеть примерно так:

Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"