1. 传统的错误处理
1.1 程序开发中常见的错误

1.2 传统错误处理方式

2. C++的异常机制

2.1 正常流程

2.2 异常流程

2.2.1 throw抛出基本类型:
#include <iostream>
#include <cstdio>
using namespace std;
class A{
public:
A(void){
cout << "A类构造" << endl;
}
~A(void){
cout << "A类析构" << endl;
}
};
int func3(void){
A a;
FILE *fp = fopen("x.txt", "r");
if(fp == NULL){
throw -1; // 抛出异常, 不会执行下面的代码,只会执行}, 这样就可以调用A的析构
}
//...
fclose(fp);
return 0;
}
int func2(void){
A a;
// 若func3中 throw抛出异常,那么这里func3()下面的代码也不会执行,只会执行},这样就可以调用A类析构
func3();
//...
return 0;
}
int func1(void){
A a;
// 若func3中 throw抛出异常,那么这里func2()下面的代码也不会执行,只会执行},这样就可以调用A类析构
func2();
//...
return 0;
}
int main(void){
try{ // 异常检测
// 检测到异常以后,会逐层返回,只执行}, 不执行代码
func1();
//并且检测到异常以后不会再执行下面的代码
cout << "test" << endl;
}
catch(int ex){ // 异常捕获
cout << "文件打开失败" << endl;
return -1;
}
}
$ ./a.out
A类构造
A类构造
A类构造
A类析构
A类析构
A类析构
文件打开失败
2.2.2 throw抛出类类型:
#include <iostream>
#include <cstdio>
using namespace std;
class FileError{
public:
FileError(const string& file, int line):m_file(file), m_line(line){
cout <<"出错位置"<< m_file <<", 出错行号" << m_line << endl;
}
private:
string m_file;
int m_line;
};
class A{
public:
A(void){
cout << "A类构造" << endl;
}
~A(void){
cout << "A类析构" << endl;
}
};
int func3(void){
A a;
FILE *fp = fopen("x.txt", "r");
if(fp == NULL){
throw FileError(__FILE__, __LINE__); //匿名的方式创建了一个FileError对象, 然后被throw抛出, 下面的throw -1; 不会执行
throw -1; // 抛出异常, 不会执行下面的代码,除了}, 这样就可以调用A的析构
}
//...
fclose(fp);
return 0;
}
int func2(void){
A a;
// 若func3中 throw抛出异常,那么这里func3()下面的代码也不会执行,只会执行},这样就可以调用A类析构
func3();
//...
return 0;
}
int func1(void){
A a;
// 若func3中 throw抛出异常,那么这里func2()下面的代码也不会执行,只会执行},这样就可以调用A类析构
func2();
//...
return 0;
}
int main(void){
try{ // 异常检测
// 检测到异常以后,会逐层返回,只执行}, 不执行代码
func1();
//并且检测到异常以后不会再执行下面的代码
cout << "test" << endl;
}
catch(int ex){ // 异常捕获
cout << "文件打开失败" << endl;
return -1;
}
// 引用做参数避免拷贝构造
catch(FileError& ex){
cout << "File open Error" << endl;
}
}
$ ./a.out
A类构造
A类构造
A类构造
出错位置a.cpp, 出错行号30
A类析构
A类析构
A类析构
File open Error
- 对于函数调用,只有知道函数中,throw会抛出的异常类型。才能去写catch语句, 所以就有了 函数的异常说明
3. 函数的异常说明

#include <iostream>
#include <cstdio>
using namespace std;
class FileError{};
class MemoryError{};
void func(void) throw (MemoryError){
// 这里抛出的对象的类型一定要是异常类型表里的一种类型
throw MemoryError();
// // 如果不是,异常不会被catch捕获,而是会被系统系统捕获, 比如下面, 然后终止这个进程
// throw FileError();
}
int main(void){
try{
func();
}
catch(MemoryError& ex){
cout << "MemoryError" << endl;
}
catch(FileError& ex){
cout << "FileError" << endl;
}
}
$ ./a.out
MemoryError
4. 标准异常类的说明

- 用一个catch处理多个异常。
#include <iostream>
#include <cstdio>
using namespace std;
class FileError:public exception{
public:
// const char* what() const _GLIBCXX_USE_NOEXCEPT{ // 也行
const char* what() const throw(){
cout << "针对文件错误的处理" << endl;
return "FileError";
}
};
class MemoryError:public exception{
public:
// const char* what() const _GLIBCXX_USE_NOEXCEPT{ // 也行
const char* what() const throw(){
cout << "针对内存错误的处理" << endl;
return "MemoryError";
}
};
void func(void) throw (MemoryError, FileError){
// 这里抛出的对象的类型一定要是异常类型表里的一种类型
throw MemoryError();
}
int main(void){
try{
func();
}
// 基类类型引用接收子类对象(向上造型)
catch(exception& ex){
// 多态语法, 调用实际被引用对象中的虚函数what
ex.what();
}
}
$ ./a.out
针对内存错误的处理
版权声明:本文为guaiderzhu1314原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。