设置触发异常
Stream缺省的情况下不抛出异常,但可由成员函数exceptions来设置这种行为。
exceptions有两种形式:
- 获取引发异常的标志(不带参数)
- 设置引发异常的标志(带参数)
// This method is not used in msvcm80.dll, so we do not need to compile it.
// Also, if we never change the exception mask, we ensure the clear() method
// will never throw any exception. See VSW#476338 for details.
iostate __CLR_OR_THIS_CALL exceptions() const
{ // return exception mask
return (_Except);
}
void __CLR_OR_THIS_CALL exceptions(iostate _Newexcept)
{ // set exception mask to argument
_Except = (iostate)((int)_Newexcept & (int)_Statmask);
clear(_Mystate);
}
比如strm.exceptions( std::ios::eofbit )
表示当Stream被设定了eofbit状态,就触发异常,异常类型为std::ios_base::failure
注:在调用exceptions设置触发异常的标志位,如果这个异常标志位已经在调用之前被设置了,此时就会立刻抛出异常。以上代码已说明一切,exceptions内部会调用clear(_Mystate)
来对原来的状态位重新设置下,从而触发异常。
使用异常的注意事项
Stream在读取数据至end-of-file时,不仅设置ios::eofbit,而且还会设置ios::failbit。所以,当发生异常时,要注意使用成员函数eof()
来区分到底是哪类异常。
try
{
cin.clear();
cin.exceptions( std::ios::eofbit | std::ios::failbit );
int a = 0;
while( cin >> a )
{
cout << a << endl;
}
}
catch( const std::ios_base::failure& e )
{
cout << "ios_base::failure occurred: " << e.what() << endl;
if ( cin.eof() )
{
cout << "end-of-file exception" << endl;
}
}
catch( ... )
{
cout << "unexpected exception" << endl;
}
以上例子演示了如何区分异常类型(在windows可通过Ctrl-Z
来产生end-of-file,在linux/unix下通过Ctrl-D
)。
检测错误+异常
我们可以结合错误检测与异常的方式,来使用自定义错误信息。通过Stream的成员函数eof()
、fail()
、bad()
来检测出错误,然后抛出自己的错误消息。
try
{
int a = 0;
while( cin >> a )
{
cout << a << endl;
}
if ( cin.eof() )
{
throw std::ios::failure("custom error information: "
"end-of-file have been occurred");
}
}
catch( const std::ios_base::failure& e )
{
cout << e.what() << endl;
}
catch( ... )
{
cout << "unexpected exception" << endl;
}