exception错误处理库学习
exception是c++标准库组件抛出的各种异常的基类,在c++开发的过程中我们经常会遇到各种各样的异常比如,打开文件失败,数组越界,等等,如果不想让程序崩溃,那么就需要使用一个异常类来处理这些异常错误,使得程序继续运行。下面我们来学习exception的基本使用。
1.异常的使用示例
我们先来看一个不使用exception的程序
#include <iostream>
#include <typeinfo>
#include <exception>
using namespace std;
class Polymorphic
{
virtual void member() {}
};
int main()
{
Polymorphic *pb = nullptr;
typeid(*pb);
cout << "Hello World!" << endl;
return 0;
}
运行
程序运行就崩溃了,然后我们再使用异常处理
#include <iostream>
#include <typeinfo>
#include <exception>
using namespace std;
class Polymorphic
{
virtual void member() {}
};
int main()
{
try {
Polymorphic *pb = nullptr;
typeid(*pb);
} catch (std::exception &e) {
std::cerr << "exception caught: " << e.what() << endl;
}
cout << "Hello World!" << endl;
return 0;
}
运行结果:
程序抛出空指针的异常,但程序不会崩溃,因此使用exception时程序出现错误时,可以抛出来,避免程序崩溃,程序员需要处理抛出的异常。
2.current_exception捕获当前异常到exception_ptr中
#include <iostream>
#include <exception>
using namespace std;
//1.current_exception捕获当前异常到exception_ptr中
void handle_exception(std::exception_ptr eptr) //按值传递
{
try {
if(eptr)
std::rethrow_exception(eptr);
} catch (const std::exception &e) {
std::cout << "Caught exception=====" << e.what() << endl;
}
}
int main()
{
std::exception_ptr eptr;
try {
std::string().at(1);//知成一个std::out_of_range
} catch (...) {
//捕获当前异常
eptr = std::current_exception();
}
handle_exception(eptr);
cout << "Hello World!" << endl;
return 0;
}
运行结果:
3.make_exception_ptr 创建一个异常对象
#include <iostream>
#include <typeinfo>
#include <exception>
using namespace std;
int main()
{
auto p = std::make_exception_ptr(std::logic_error("logic_error"));
try {
std::rethrow_exception(p);
} catch (const std::exception& e) {
std::cout << "exception caught:" << e.what() << endl;
}
cout << "Hello World!" << endl;
return 0;
}
运行结果:
4.rethrow_exception 从一个 std::exception_ptr 抛出异常
#include <iostream>
#include <typeinfo>
#include <exception>
#include <vector>
using namespace std;
int main()
{
std::exception_ptr p;
try {
std::vector<int> myvector(10);
myvector.at(20) = 100; //vector::at throws on out-of-range
} catch (const std::exception& e) { //捕获异常
cout << "e.what ======== " << e.what() << endl;
p = current_exception();
cout << "exception caught, but continuing... typeid(p).name ====" << typeid(p).name() << endl;
}
cout << "(after exception)" << endl;
try {
std::rethrow_exception(p);
} catch (const std::exception& e) {
std::cout << "exception caught: " << e.what() << endl;
}
cout << "Hello World!" << endl;
return 0;
}
运行结果:
5.terminate 异常终止
#include <iostream>
#include <typeinfo>
#include <exception>
#include <vector>
using namespace std;
int main()
{
char *p;
cout << "Attempting to allocate 2GB..." << endl;
try {
p = new char[2147483647]; //2147483648====>2GB
} catch (const exception &e) {
cout << "excepter=======e.what()======= " << e.what() << endl;
cout << "Error: could not allocate storage." << endl;
terminate();
}
delete[] p;
cout << "Hello World!" << endl;
return 0;
}
运行结果:
6.设置终止异常函数
#include <iostream>
#include <typeinfo>
#include <exception>
#include <vector>
using namespace std;
void myterminate()
{
std::cerr << "terminate handler called" << endl;
abort(); //forces abnormal termination
}
int main()
{
std::set_terminate(myterminate);
throw 0; //unhandled exception: calls terminate handler
cout << "Hello World!" << endl;
return 0;
}
运行结果:
7.throw_width_nested嵌套异常
#include <iostream>
#include <typeinfo>
#include <exception>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
void openFile(const std::string &fileName)
{
try {
std::ifstream file(fileName);
file.exceptions(std::ios_base::failbit);
} catch (...) {
std::cout << "openFile=====fileName===" << fileName << endl;
std::throw_with_nested(std::runtime_error("Couldn't open " + fileName));
}
}
//捕捉异常并将其包装于nested_exception
void throwWithNested()
{
try {
openFile("nonexistent.txt");
} catch (const exception &e) {
cout << "throwWithNested()====e.what===" << e.what() << endl;
}
}
int main()
{
try {
throwWithNested();
} catch (const std::exception &e) {
cout << "exception =====e.what====== " << e.what() << endl;
}
cout << "Hello World!" << endl;
return 0;
}
运行结果:
8.rethrow_if_nested如果是嵌套抛出异常
#include <iostream>
#include <typeinfo>
#include <exception>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
// 打印异常的解释性字符串。若异常内嵌,则递归打印其保有的异常的解释
void printException(const std::exception &e, int level = 0)
{
cout << std::string(level, ' ') << "exception: " << e.what() << endl;
try {
std::rethrow_if_nested(e);
} catch (const std::exception &e) {
printException(e, level + 1);
}catch(...) {
cout << "printException=======e.what== " << e.what() << " level = " << level << endl;
}
}
void openFile(const std::string &fileName)
{
try {
std::ifstream file(fileName);
file.exceptions(std::ios_base::failbit);
} catch (...) {
std::cout << "openFile=====fileName===" << fileName << endl;
std::throw_with_nested(std::runtime_error("Couldn't open " + fileName));
}
}
//捕捉异常并将其包装于nested_exception
void throwWithNested()
{
try {
openFile("nonexistent.txt");
} catch (const exception &e) {
cout << "throwWithNested()====e.what===" << e.what() << endl;
std::throw_with_nested(e);
}
}
int main()
{
try {
throwWithNested();
} catch (const std::exception &e) {
printException(e);
}
cout << "Hello World!" << endl;
return 0;
}
运行结果:
参考:
<exception> - C++ Reference
标准库头文件 <exception> - cppreference.com