я пробовал разные способы; это работает для меня:
Начните с создания подкласса runtime_error :
/*----------------------------------------------------------------------*/
/* subclass runtime_error for safe exceptions in try/throw/catch */
#include <stdexcept>
/* a little preprocessor magic here -- makes a subclass of runtime_error*/
#define NEWERROR( NE ) class NE : public runtime_error { \
public: NE ( string const& error ) : runtime_error(error) {} }
NEWERROR( FileError );
NEWERROR( NetworkError );
NEWERROR( StringError );
NEWERROR( CofeeError );
/*----------------------------------------------------------------------*/
Тогда вы можете создать несколько экземпляров ваших исключений.
/*----------------------------------------------------------------------*/
/* some example pre-defined exceptions */
FileError ReadOnly ( "ReadOnly" );
FileError FileNotFound ( "FileNotFound" );
NetworkError TimeOutExceeded ( "TimeOutExceeded" );
NetworkError HostNotFound ( "HostNotFound" );
CoffeeError OutOfCoffee ( "OutOfCoffee" );
/*----------------------------------------------------------------------*/
Явно уведомить компилятор, что ваша функция может выдать исключение
или программа, вероятно, прекратит работу в указанной точке, и данные могут быть потеряны или повреждены
если ресурсы используются в то время.
«Убедитесь, что вы можете и поймать все, что вы можете бросить.»
(я использую общий runtime_error , потому что его бросание и перехват охватывают все
Мои исключения, а также системные.)
/*----------------------------------------------------------------------*/
/* example function that may throw an exception */
#include <fstream>
ifstream& getFileStream (string fname) throw (runtime_error)
{
if ( fname == "" )
throw StringError( "<getFileStream> fname:empty string" );
// processing stops here if thrown
try
{
ifstream Inputfstream;
ifstream& ifsref = Inputfstream;
// ifstream has its own <legacy> exception
// mechanisms and procedures
ifsref.exceptions ( ifstream::failbit | ifstream::badbit );
ifsref.open (fname , ifstream::in); // could fail ==> ifstream::failure exception
}
catch (ifstream::failure e)
{
throw FileError( fname + string(e.what() ) );
}
return ifsref;
}
/*----------------------------------------------------------------------*/
тогда в вашем try / catch
/*----------------------------------------------------------------------*/
catch (FileNotFound fnf) //catch a specific error
{
if (DEBUG) cerr << "[File Not Found Error: " << fnf.what() << "]" << endl;
... (handle it) ...
}
catch (FileError fe) //catch a specific type
{
if (DEBUG) cerr << "[File Error: " << fe.what() << "]" << endl;
... (handle it) ...
}
catch (runtime_error re ) // catch a generic type
{
if (DEBUG) cerr << "[Runtime error: " << re.what() << "]" << endl;
// determine type by string comparison
if ( re.what() == string("ResourceNotavailable") ) ...
if ( re.what() == string("NetWorkError") ) ...
...
}
catch ( ... ) // catch everything else
{ ... exit, rethrow, or ignore ... }
/*----------------------------------------------------------------------*/
Класс runtime-error имеет хорошую поддержку в стандартных библиотеках c ++,
и компиляторы знают об этом внутренне, и как оптимизировать память и диспетчеризацию,
так что вы можете безопасно и уверенно использовать их в разных базах кода. Код является переносимым и совместимым со многими различными компиляторами и архитектурами.
Может быть предпочтительнее и несколько быстрее отлавливать каждую ошибку отдельно в предложении catch, от более специфического к более универсальному, если вы чувствуете, что последовательность совпадений строк является ужасной тратой ресурсов процессора и памяти (хотя компилятор оптимизирует их) ,
<stdexcept>
дает вам несколько видов исключений в 2 группах:
Логические ошибки:
logic_error
domain_error
invalid_argument
length_error
out_of_range
Ошибки времени выполнения:
runtime_error
range_error
overflow_error
underflow_error
Синтаксис использования немного отличается для некоторых из них.
Обычная мудрость в C ++ говорит, что ваши исключения должны быть относительно "плоскими",
Это означает, что большие иерархии определенных категорий исключений следует избегать в
предпочтение кратких общих, но информативных для общих задач программирования. Задачи, специфичные для предметной области, такие как логика сетевой системы, высшая математика и т. Д., Могут выиграть от специфики, но это может быть легко достигнуто путем создания интеллектуальных строк ошибок с общими исключениями времени выполнения / логики.
Наконец, Моя точка зрения : всего этого вы можете достичь,
бросать и ловить только runtime_error .
Вам не нужно создавать целую сумку со специфическими исключениями
(как это делает Java) для каждого класса, каждый обрабатывает одну конкретную ошибку.