这三个关键字通常是c++在处理异常时使用的
try :try块中的代码通过throw抛出异常,再通过catch捕获这个异常。
throw : 抛出异常 。
catch :捕获throw抛出的异常。
例如以下语句:
try
{
throw XXX;
}
catch (T1& e)
{
cout << "error1" <<endl;
}
catch (T2& e)
{
cout << "error2" <<endl;
}
catch (T3& e)
{
cout << "error3" <<endl;
}
catch (...)//...可捕获任意异常
{
cout << "垃圾桶" <<endl;
}
首先在try代码块中通过throw抛出异常,catch通过不同的异常类型去捕获,再输出相应的异常信息,这是这三个关键字的大致使用流程,下面是几个注意的点。
1.throw抛出的对象后,优先选中最近的catch进行配对,配对不成功,与下一个catch配对,以此类推。
class Base
{
public:
int m_a;
Base(int a = 0) :
m_a(a)
{}
};
class Test:public Base
{
public:
int m_b;
Test(int a = 0,int b = 0 ) :
Base(a),
m_b(b)
{}
};
int main()
{
try
{
Base a(10);
Test b(20,30);
throw b;
}
catch (Base& e)
{
cout << e.m_a << endl;
}
catch (Test& e)
{
cout << e.m_b <<endl;
}
system("pause");
return 0;
}
由此例子看出:基类的被派生类继承后,派生类的异常可以被基类捕获(反之不行)。
2.catch(T& e),e是临时的拷贝对象,在catch代码段结束后,对象自动销毁。
3.throw可跨栈操作
double Division(int a, int b)
{ // 当b == 0时抛出异常
if (b == 0)
{
throw "Division by zero condition!";
}
else
{
return ((double)a / (double)b);
}
}
void Func()
{
int len, time;
cin >> len >> time;
cout << Division(len, time) << endl;
}
int main()
{
try
{
Func();
}
catch (const char* errmsg)
{
cout << errmsg << endl;
}
catch(...)
{
cout<<"unkown exception"<<endl;
}
return 0;
}
4.最好在构造和析构函数里面不要使用,极大可能会导致对象未初始化和内存泄漏,如需使用,使用智能指针可解决,
5.C++标准库的异常体系
异常名称 | 解释说明 |
---|---|
std::exception | 所有异常的基类 |
std::bad_alloc | 抛出new的异常 |
std::bad_cast | 抛出dynamic_cast异常 |
std::bad_typeid | 抛出typeid异常 |
这里只列出四种比较常见的异常,大多使用都会用基类的异常名来捕获。
int main()
{
try{
vector<int> v(10, 5); // 这里如果系统内存不够也会抛异常
v.reserve(1000000000);// 这里越界会抛异常
v.at(10) = 100;
}
catch (const exception& e) // 这里捕获父类对象就可以
{
cout << e.what() << endl;
}
catch (...)
{
cout << "Unkown Exception" << endl;
}
return 0;
}