平时就只是简单的使用trycatch,并未深入的了解,今天记录一下认识了多一点的异常捕获机制。
先记录要点:(对于自己的要点)
1. assert 也属于异常捕获机制的一种,只适用开发阶段的调式作用,通过#define NDEBUG来使其失效。
2. 异常匹配,想抛出自定义类的异常,需要用引用,防止异常信息将其丢失,如下
class X
{
public:
class Trouble {};
class SmallT : public Trouble {};
class BigT : public Trouble {};
void f()
{
throw BigT();
}
};
int main()
{
X x;
try
{
x.f();
}
catch(X::Trouble&)
{
...
}
catch(X::SmallT &)
{
...
}
catch(X::BigT &)
{
...
}
}
后面两个异常始终捕获不到,因为第一个异常全部捕获了。
3. 之前一直没注意到这块,后面看了书才发现到,清理。异常捕获到之后,如何能够正常的继续执行,捕获异常之后,离开作用域的变量又是如何进行析构。
在try块内new的时候,如果out of memory,此时异常发生,但是new出来的数据却没有回收,造成泄露。
#include <iostream>
using namespace std;
template<class T,int sz = 1>
class PWrap
{
T* ptr;
public:
class RangeError {};
PWrap()
{
ptr = new T[sz];
cout << "PWrap constructor" << endl;
}
~PWrap()
{
delete[] ptr;
cout << "PWrap delete" << endl;
}
T& operator[](int i) throw(RangeError)
{
if (i >= 0 && i < sz) return ptr[i];
throw RangeError();
}
};
class Cat
{
public:
Cat()
{
cout << "cat()" << endl;
}
~Cat()
{
cout << "~cat()" << endl;
}
};
class dog
{
public:
void* operator new[](size_t t)
{
cout << "new dog" << endl;
throw 1;
}
void operator delete[](void* p)
{
cout << "delete dog" << endl;
delete[](p);
}
};
class Animals
{
public:
PWrap<Cat, 3> cats;
PWrap<dog> dogs;
public:
Animals()
{
cout << "Animals()" << endl;
}
~Animals()
{
cout << "~Animals()" << endl;
}
};
int main()
{
try
{
Animals a;
}
catch (int)
{
cout << "haha";
}
catch (...)
{
cout << "catch error" << endl;
}
std::cout << "Hello World!\n";
system("pause");
}
结果:
cat()
cat()
cat()
PWrap constructor
new dog
~cat()
~cat()
~cat()
PWrap delete
hahaHello World!
主要看几点:
1. 为什么离开了try的作用域,没有annimal的析构函数,因为构造没完成,所以没有析构。
2. 这样的技术叫资源获得式初始化 RAII,使所有事物都是对象,使得对象对资源的控制的时间与对象的生命周期相等。
3. PWrap中的函数后throw