c++构造函数中抛出异常的用途和用法
2016-01-18 16:19
441 查看
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
执行结果:演示了对象构建失败throw, catch 的运行机制。前期对象被析构,后期被跳过。
./Test3
构造一个Base类型的对象,对象名为:obj1
构造一个Component类型的对象
销毁一个Component类型的对象
销毁一个Base类型的对象,对象名为:obj1
catch:1 obj:0
也有点象函数,可以传递对象。
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() { throw 0; } 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
相关文章推荐
- static修饰符 (在类中的意义及用法)
- C++中函数使用的基本知识学习教程
- cppcheck工具的使用
- c++平台国际化前期工作技巧
- 实例讲解在C++的函数中变量参数及默认参数的使用
- C++对象模型
- 结合C++11的新特性来解析C++中的枚举与联合
- 【Accelerated C++】重点回顾
- c++线程同步和通信
- C++ OOP手册
- C++编程中的命名空间基本知识讲解
- c++ 程序设计 wee4 作业 大整数四则运算
- VC++6.0插件系列(绝对经典)
- C++之路进阶——2-set(满汉全席)
- 一元多项式相加(C语言实现)
- C++之路进阶——2-set(奶牛议会)
- C/C++中volatile关键字详解
- C/C++ Volatile关键词深度剖析
- 区分 C++ 指针跟引用
- C++流程控制中用于跳转的return和goto语句学习教程