当前位置:   article > 正文

c++构造函数中抛出异常的用途和用法_c++ 构造函数抛出异常

c++ 构造函数抛出异常

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

  1. $ cat test.h
  2. #ifndef __MYTEST_BASE
  3. #define __MYTEST_BASE
  4. #include <string>
  5. using namespace std;
  6. class Component
  7. {
  8. public:
  9. Component();
  10. virtual ~Component();
  11. };
  12. class Base
  13. {
  14. public:
  15. Base(string name="");
  16. virtual ~Base();
  17. void Func() throw();
  18. void Other(){};
  19. protected:
  20. string m_name;
  21. };
  22. class Derive : public Base
  23. {
  24. public:
  25. Derive(string name="");
  26. virtual ~Derive();
  27. protected:
  28. Component m_component;
  29. };
  30. #endif

  1. cat test.cpp
  2. #include <iostream>
  3. #include "test.h"
  4. Component::Component ()
  5. {
  6. cout << "构造一个Component类型的对象" << endl;
  7. }
  8. Component::~Component ()
  9. {
  10. cout << "销毁一个Component类型的对象"<< endl;
  11. }
  12. Base::Base (string name) : m_name(name)
  13. {
  14. cout << "构造一个Base类型的对象,对象名为:"<<m_name << endl;
  15. }
  16. Base::~Base ()
  17. {
  18. cout << "销毁一个Base类型的对象,对象名为:"<<m_name << endl;
  19. }
  20. void Base::Func() throw() //这种写法显然是有点问题的,声明说不抛出异常,实现又抛出异常,
  21. { // 实验结果是异常是抛出去了,程序被terminate.
  22. throw 0; // 而且这个异常不能被catch, 只能terminate, 你可以调用这个函数试试!
  23. }
  24. Derive::Derive (string name ) :
  25. Base(name), m_component()
  26. {
  27. throw 1 ; //在Derive对象的构造函数中抛出了一个异常!则原来的构建过程会自动被析构
  28. cout << "构造一个Derive类型的对象,对象名为:"<<m_name << endl; // 后面的语句不会被执行
  29. }
  30. Derive::~Derive ()
  31. {
  32. cout << "销毁一个Derive类型的对象,对象名为:"<<m_name << endl; //构建不成功,不会被执行
  33. }

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

执行结果:演示了对象构建失败throw, catch 的运行机制。前期对象被析构,后期被跳过。
./Test3
构造一个Base类型的对象,对象名为:obj1
构造一个Component类型的对象
销毁一个Component类型的对象
销毁一个Base类型的对象,对象名为:obj1
catch:1 obj:0

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/715001
推荐阅读
相关标签
  

闽ICP备14008679号