赞
踩
throw-catch 语句是C++的机制,有点像goto语句,一扔一接。
也有点象函数,可以传递对象。
throw 什么呢?
throw 表达式
表达式可以是数值,变量,带运算符的表达式
例如:
throw 0;
throw 1;
throw 0.1;
int a=3;
throw a
thow a+b*c;
程序执行throw 语句时,会自动调用析构器,析构已经构造的部分。
然后跳过后面语句,转而执行到catch 语句。如果找不到对应的类型catch 语句
则catch(...) 将会执行, 如果catch(...)没有定义, 则unexpected 会被执行
它默认会调用terminate函数, 可以通过set_unexpected 改变它的行为。
同样,也可以调用set_terminate()改变terminate 函数的行为.
void fun (); // 能抛出任何类型的异常
void fun () throw(except1,except2,except3)
// 后面括号里面是一个异常参数表,本例中只能抛出这3中异常
void fun () throw() // 参数表为空,不能抛出异常
这只是表面现象,并没有限制作用,结构不好的程序仍然可以抛出不在异常列表中的异常,
此时当然还是走terminate 函数
catch()依据变量类型来区分
catch(int &a);
catch(double &d);
catch(char *&c);
throw-cache 我看还是在c++对象构建失败时用途最大。其它场景比较容易理解。
下面给个例子。
该实例用来帮助理解在构造函数中抛出异常的用途和用法。
它有三个文件构成,关键点处都给出了注释。
test.h, test.cpp,main.cpp
- $ cat test.h
- #ifndef __MYTEST_BASE
- #define __MYTEST_BASE
- #include <string>
- using namespace std;
-
- class Component
- {
- public:
- Component();
- virtual ~Component();
- };
-
- class Base
- {
- public:
- Base(string name="");
- virtual ~Base();
- void Func() throw();
- void Other(){};
-
- protected:
- string m_name;
- };
- class Derive : public Base
- {
- public:
- Derive(string name="");
- virtual ~Derive();
-
- protected:
- Component m_component;
- };
- #endif

- cat test.cpp
- #include <iostream>
- #include "test.h"
-
- Component::Component ()
- {
- cout << "构造一个Component类型的对象" << endl;
- }
-
- Component::~Component ()
- {
- cout << "销毁一个Component类型的对象"<< endl;
- }
-
-
- Base::Base (string name) : m_name(name)
- {
- cout << "构造一个Base类型的对象,对象名为:"<<m_name << endl;
- }
-
- Base::~Base ()
- {
- cout << "销毁一个Base类型的对象,对象名为:"<<m_name << endl;
- }
-
- void Base::Func() throw() //这种写法显然是有点问题的,声明说不抛出异常,实现又抛出异常,
- { // 实验结果是异常是抛出去了,程序被terminate.
- throw 0; // 而且这个异常不能被catch, 只能terminate, 你可以调用这个函数试试!
- }
-
-
-
- Derive::Derive (string name ) :
- Base(name), m_component()
- {
- throw 1 ; //在Derive对象的构造函数中抛出了一个异常!则原来的构建过程会自动被析构
-
- cout << "构造一个Derive类型的对象,对象名为:"<<m_name << endl; // 后面的语句不会被执行
- }
-
- Derive::~Derive ()
- {
- cout << "销毁一个Derive类型的对象,对象名为:"<<m_name << endl; //构建不成功,不会被执行
- }

- cat main.cpp
- #include <iostream>
- #include "test.h"
- // 在构造函数中抛出异常是解决构造函数失败的唯一办法,它很好的解决了函数析构问题
- // 通过构建参数指明构建是否成功,失败,不能解决对象析构问题
- int main(int argc, char *argv[])
- {
- (void)argc;
- (void)argv;
- Derive* obj=NULL; // 编译器对0进行了无比关照,不信写1试试.就会告诉你非法转换
- try
- {
- // 对象构造时将会抛出异常
- obj = new Derive("obj1");
-
- obj->Func(); // 由于构造抛出了异常,这里不会被执行
- obj->Other();
- }
- catch(int i)
- {
- // obj 指针依然为空
- cout << "catch:" << i <<" obj:"<<obj<< endl;
- }
- catch(...)
- {
- cout << "unknow exception"<< endl;
- }
- }

执行结果:演示了对象构建失败throw, catch 的运行机制。前期对象被析构,后期被跳过。
./Test3
构造一个Base类型的对象,对象名为:obj1
构造一个Component类型的对象
销毁一个Component类型的对象
销毁一个Base类型的对象,对象名为:obj1
catch:1 obj:0
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。