我读了几个关于异常和错误代码的使用的讨论,以及它们何时适合。
我相信在我的情况下例外情况会更好,但我有一个特定的问题:
如果我抛出一个std :: runtime_error(“这是一个错误”),然后我抓住它,我找不到错误,我只是理解有错误。
我正在寻找的是一个异常,我可以抛出并添加一个错误代码,以便稍后我可以检查错误代码,当我抓住它时,有些事情如下:
enum errorCodes
{
error_1,
error_2,
error_3
}
try
{
throw std::runtime_error(error_1,"can not do the job!");
}
catch (std::runtime_error & err)
{
switch (err.errorCode)
{
case error_1:
// I can not contunue, so re throw it
rethrow err;
case error_2:
// it is not important for me, so I can continue
break;
case error_3:
//Oh, I need to do something before continue
re_init();
break;
default:
rethrow err;
}
我可以编写这样的异常,但在此之前,我想知道STL或BOOST中是否存在这种类型的异常?
有没有更好的方法(我不想抛出不同类型的异常,因此从我的角度来看,捕获不同类型的异常不是解决方案。
答案 0 :(得分:3)
是的,有std::system_error
。它来自std::runtime_error
。这是非常面向Unix的,但它确实支持错误代码,我建议你这样使用它。
以下代码演示了如何为应用程序特定的错误代码定义一个自己的错误类别:
#include <string>
#include <system_error>
#include <typeinfo>
namespace my{
struct Error_code
{
enum Enum
{
error_1 = 101,
error_2 = 102,
error_3 = 103
};
};
class App_error_category
: public std::error_category
{
using Base = std::error_category;
public:
auto name() const noexcept
-> char const*
override
{ return "App error"; }
auto default_error_condition( int const code ) const noexcept
-> std::error_condition
override
{ (void) code; return {}; }
auto equivalent( int const code, std::error_condition const& condition ) const noexcept
-> bool
override
{ (void) code; (void) condition; return false; }
// The intended functionality of this func is pretty unclear.
// It apparently can't do its job (properly) in the general case.
auto equivalent( std::error_code const& code, int const condition ) const noexcept
-> bool
override
{ return Base::equivalent( code, condition ); }
auto message( int const condition ) const
-> std::string
override
{ return "An application error occurred, code = " + std::to_string( condition ); }
constexpr
App_error_category(): Base{} {}
};
auto app_error_category()
-> App_error_category const&
{
static App_error_category the_instance;
return the_instance;
}
class App_error
: public std::system_error
{
using Base = std::system_error;
public:
auto app_error_code() const
-> Error_code::Enum
{ return static_cast<Error_code::Enum>( code().value() ); }
App_error( Error_code::Enum const code )
: Base{ code, app_error_category() }
{}
App_error( Error_code::Enum const code, std::string const& description )
: Base{ code, app_error_category(), description }
{}
};
} // namespace my
void foo()
{
try
{
throw my::App_error( my::Error_code::error_1, "can not do the job!" );
}
catch( my::App_error const& x )
{
switch( x.app_error_code() )
{
case my::Error_code::error_1:
// I can not contunue, so re throw it
throw;
case my::Error_code::error_2:
// it is not important for me, so I can continue
break;
case my::Error_code::error_3:
//Oh, I need to do something before continue
//re_init();
break;
}
}
}
#include <iostream>
#include <stdlib.h> // EXIT_SUCCESS, EXIT_FAILURE
using namespace std;
auto main()
-> int
{
try
{
foo();
return EXIT_SUCCESS;
}
catch( exception const& x )
{
cerr << "!" << x.what() << endl;
}
return EXIT_FAILURE;
}
使用Visual C ++ 2015和MingW g ++ 6.4.0生成输出
!can not do the job!: An application error occurred, code = 101
通常,定义特定异常类比使用错误代码更实际。但是,对于系统错误代码,将这些代码传递给异常更为实际。对于 ,可以避免上面显示的复杂性,因为std::system_category
非常适合。
简而言之,这里的复杂性源于你不要顺应潮流的要求,而是在与当前有所不同的方向上。
答案 1 :(得分:2)
考虑使用开箱即用的std::system_error
。
请注意,简单地使用throw;
而不使用参数是一种远更好的方法来重新抛出异常(您似乎正在使用throw err;
),因为前者将抛出引用而不是按值:例如,后者可能导致对象切片。