异常处理机制
- 若是有异常则通过
throw操作创建一个异常对象并抛掷 - 将可能抛出异常的程序段嵌入到
try块之中,控制通过正常的顺序执行到try语句,然后执行try块内的保护段 - 如果在保护段执行期间没有引起异常,那么跟在
try块后的catch子句就不执行,程序从try块后跟随者最后一个catch子句后面的语句继续执行下去。 catch子句按其在try块后出现的顺序被检查,匹配的catch子句将捕获并处理异常- 如果匹配的处理器未找到,则执行函数
teminate将自动调用,其缺省功能是调用abort终止程序 - 处理不了的异常,可以在
catch的最后一个分支,使用throw的方法继续向上扔
异常处理的好处就是能将异常处理和正常函数流程进行分离,正常流程只处理函数业务上的逻辑,异常处理可以交给单独的异常处理函数进行处理。
栈解旋
异常抛出后,从进入try块起,到异常被抛出前,这期间在栈上的构造的所有对象,都会被自动析枸。析枸的顺序与构造的顺序相反,这个过程被称为栈的解旋(unwinding)
异常接口声明
为了加强程序的可读性,可以在函数声明中列出可能抛出的所有异常类型,例如:void func() throw(A,B,C,D),这个函数func()能够且只能抛出A,B,C,D及其子类型的异常。
如果函数声明中国捏没有包含任何类型的异常接口声明,则此函数可以抛出任何类型的异常,例如:void func()
一个不抛出任何异常的函数可以声明为void func() throw()
如果一个函数抛出了它的异常接口声明不允许抛出的异常,unexpected函数会被调用,该函数默认行为调用terminate函数终止程序。
C++标准异常

异常 描述
std::exception 该异常是所有标准 C++ 异常的父类。
std::bad_alloc 该异常可以通过 new 抛出。
std::bad_cast 该异常可以通过 dynamic_cast 抛出。
std::bad_exception 这在处理 C++ 程序中无法预期的异常时非常有用。
std::bad_typeid 该异常可以通过 typeid 抛出。
std::logic_error 理论上可以通过读取代码来检测到的异常。
std::domain_error 当使用了一个无效的数学域时,会抛出该异常。
std::invalid_argument 当使用了无效的参数时,会抛出该异常。
std::length_error 当创建了太长的 std::string 时,会抛出该异常。
std::out_of_range 该异常可以通过方法抛出,例如 std::vector 和 std::bitset<>::operator。
std::runtime_error 理论上不可以通过读取代码来检测到的异常。
std::overflow_error 当发生数学上溢时,会抛出该异常。
std::range_error 当尝试存储超出范围的值时,会抛出该异常。
std::underflow_error 当发生数学下溢时,会抛出该异常。
//
// Created by andrew on 2021/4/24.
//
#include <iostream>
#include <exception>
using namespace std;
/*
* 异常的基本语法
* */
class error : std::exception {
const char * what() const noexcept override;
};
const char *error::what() const noexcept {
return exception::what();
}
class construct_test {
public:
construct_test() {
cout << "construct test" << endl;
};
~construct_test() {
cout << "destruct test" << endl;
}
};
int divide_demo(int x, int y) {
construct_test constTest;
if (y == 0) {
cout << "before throw " << endl;
// throw之前将所有的栈进行析枸
throw x; // 抛出 int类型 异常
}
cout << "divide y " << x / y << endl;
return 0;
}
class Student {
public:
explicit Student(int &&studentAge) {
if (studentAge > 250) {
throw out_of_range("age is too big.");
}
cout << "construct student" << endl;
age = studentAge;
}
~Student() {
cout << "destruct student" << endl;
}
private:
unsigned int age{};
};
/*
* 从标准异常类中进行继承
* */
class MyException : exception {
public:
explicit MyException(const char *p) {
this->m_p = p;
}
~MyException() override = default;
virtual const char* what() {
cout << "MyException " << m_p << endl;
return m_p;
}
private:
const char *m_p{};
};
void TestMyException() {
throw MyException("func exception");
}
/*
* 构造函数中没有返回值,也通常需要通过异常来处理构造函数中的异常
* */
int main(int argc, char*argv[]) {
try {
// 1.将可能引起异常的代码放到try的地方
divide_demo(10, 2);
divide_demo(10, 0);
}
catch (int e) {
cout << "after throw" << endl;
cout << "e = " << e << endl;
} // ... 是其他未知类型的异常
catch (...) {
}
/*
* 使用标准异常
* */
try {
Student student(300);
}
catch (out_of_range &eOut) {
cout << eOut.what() << endl;
}
try {
TestMyException();
}
catch (MyException &exceptData) {
exceptData.what();
}
catch (...) {
cout << "unknow error" << endl;
}
return 0;
}


1万+

被折叠的 条评论
为什么被折叠?



