您的位置:首页 > 编程语言 > C语言/C++

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

$ 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: