赞
踩
C++标准程序库有两种方式:
std classes
,支持具体的错误处理,他们检测所有可能发生的错误,并于错误发生时抛出异常STL
,valarrays
等,效率重于安全,因此几乎不检验逻辑错误,并且只检测执行期(runtime
)错误ps:逻辑错误和运行期程序的区别:
standard exception classes
)语言本身或者标准程序库所抛出的所有异常,都派生自基类exception
。类层次结构如下:
带着可以分为三组:
所用头文件
#include <exception>
#include <new>
#include <typeinfo>
#include <ios>
#include <stdexcept>
#include <future>
此类异常用以支撑某些语言特性。所以,它们不是标准库的一部分,而是核心语言的一部分
如果以下操作失败,就会抛出这一类的异常:
dynamic_cast
失败时,抛出bad_cast
异常RTTI
过程中,如果交给typeid操作符的实参是0或者空指针,typeid操作符会bad_typeid
异常bad_exception
是用来处理非预取的异常的。它可以用函数unexpected()抛出,该函数会在某个函数抛出的异常不再异常明细内时被调用。然而注意,C++11其不再鼓励使用异常明细这些异常总是派生自logic_error
。所谓的[逻辑错误]就是应该在程序中避免的错误。C++标准程序库提供以下逻辑错误类别:
invalid_argument
表示无效参数length_error
指出某些行为“可能超过了最大极限”。比如传入的字符串长度太长out_of_range
指出参数值“不在预期范围内”。比如vector超过索引范围domain_error
指出专业领域范围内的错误。future_error
用来指出当使用非同步系统调用时发生的逻辑差错。注意,此范围内的运行期差错是一般由class system_error发出派生自runtime_error
,用来指出“不在程序范围内,而且不容易回避”的事件
range_error
:内部计算时发生区间错误overflow_error
:算术运算时发生上溢位underflow_error
:算术运算时发生下溢位new
操作失败,bad_alloc
异常,除非用的是new的nothrow版本ios_base::failure
。当数据流由于错误或由于到达文件尾端而发生状态改变时,就可能抛出这个异常是什么
对所有标准异常类,what可以用来获取“类型以外的附加信息”,它返回一个以null结尾的byte string
class exception
{
public:
virtual const char* what() const noexcept;
}
使用示例
#include <iostream>
using namespace std;
int main(int argc,char *argv[]){
try {
throw std::runtime_error("Out of memory");
} catch (runtime_error &e) {
printf("%s\r\n", e.what());
}
return 0;
}
差错码 和 差错状态
是什么?
和它类似的是,有个叫做 差错码 和 差错状态的东西也可以获取错误详情。
针对异常,C++标准库有时候给出差错码,有时候给出差错对象。C++标准库分别为差错码和差错对象提供了两个不同的类型:class std::error_code和std std::error_condition,它们本质上都是枚举类。我们来看下它是怎么用的
怎么用?
int main(){
std::error_condition edtion;
if(edtion == std::errc::invalid_argument){
}else if(edtion == std::future_errc::future_already_retrieved){
}
std::error_code ecode;
if(ecode == std::io_errc::stream){
}else if(ecode == std::errc::io_error){
}
}
另外,所有异常类比如std::system_error提供了非虚成员函数code(),它会返回一个** std::error_code**对象
class system_error : public std::runtime_error
{
public:
virtual const char* what() const noexcept;
const error_code& code() const noexcept ;
};
class future_error : public std::logic_error
{
public:
virtual const char* what() const noexcept;
const error_code& code() const noexcept ;
};
而std::error_code(本质是一个class)提供了成员函数,可以获得具体的错误细节
struct error_code
{
public:
int value() const noexcept;
const error_category& category() const noexcept ;
string message() const ;
explicit operator bool() const noexcept;
error_condition default_error_condition(int __i) const noexcept;
.....
};
为什么要这样设计呢?
struct error_condition
{
int value() const noexcept;
const error_category& category() const noexcept ;
string message() const ;
explicit operator bool() const noexcept;
....
};
/// error_category
class error_category
{
public:
virtual const char* name() const noexcept;
virtual string message(int) const = 0;
virtual error_condition default_error_condition(int __i) const noexcept;
bool operator<(const error_category& __other) const noexcept;
bool operator==(const error_category& __other) const noexcept;
bool operator!=(const error_category& __other) const noexcept;
}
C++标准库提供了如下分类名称:
每一个分类都有响应的全局函数,返回分类:
因此,对于每一个差错码对象,我们都可以检查它是不是IO failure:
ios_base::failure e("aa");
if( e.code().category() == std::iostream_category()){
}
使用示例
template <typename T>
void processCodeException (const T& e)
{
using namespace std;
auto c = e.code();
cerr << "- category: " << c.category().name() << endl;
cerr << "- value: " << c.value() << endl;
cerr << "- msg: " << c.message() << endl;
cerr << "- def category: "
<< c.default_error_condition().category().name() << endl;
cerr << "- def value: "
<< c.default_error_condition().value() << endl;
cerr << "- def msg: "
<< c.default_error_condition().message() << endl;
}
其他成员,用的很少,只是分组生成、复制、赋值、销毁等操作
理论
(1)可以抛出标准异常
(2)不可以抛出基础的exception异常,也不可以抛出任何对语言支持而设计的异常,比如bad_cast、bad_typeid、bad_exception
使用
throw std::out_of_range("std::out_of_range");
throw std::system_error(std::make_error_code(std::errc::invalid_argument));
throw std::system_error(std::make_error_code(std::errc::invalid_argument), "invalid_argument");
exception classes
)中派生新异常[待补充]还可以在程序中自定义一个异常类,这个类必须直接或者间接的继承exception,同时还必须确保其虚函数**what()和code()**可用
#include <iostream> using namespace std; class InterruptException : public std::runtime_error { public: InterruptException() : std::runtime_error("InterruptException") {} ~InterruptException() {} }; static double quotient() { throw InterruptException(); // terminate function return 1.1; } int main(int argc,char *argv[]){ try { double result = quotient(); std::cout << "The quotient is: " << result << std::endl; } catch (InterruptException& divideByZeroException) { std::cout << "Exception occurred: " << divideByZeroException.what() << std::endl; // Exception occurred: attempted to divide by zero } }
C++11起,可以将异常存储到类型为exception_prt的对象中,稍后处理
#include <exception> #include <system_error> #include <future> #include <iostream> std::exception_ptr expr; void foo(){ try { throw std::out_of_range("std::out_of_range"); } catch (...) { expr = std::current_exception(); } } void bar(){ if(expr != nullptr){ std::rethrow_exception(expr); } } int main(){ foo(); bar(); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。