异常与继承、异常与指针、异常规格说明


一、异常与继承

如果异常类型为C++的类,并且该类有其基类,则应该将派生类的错误处理程序放在前面,基类的错误处理程序放在后面

C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include<iostream>
#include<string>

usingnamespacestd;

classMyException
{
public:
MyException(constchar*message)
:message_(message)
{
cout<<"MyException..."<<endl;
}
MyException(constMyException&other):message_(other.message_)
{
cout<<"CopyMyException..."<<endl;
}
virtual~MyException()
{
cout<<"~MyException..."<<endl;
}

constchar*what()const
{
returnmessage_.c_str();
}
private:
stringmessage_;
};

classMyExceptionD:publicMyException
{
public:
MyExceptionD(constchar*message)
:MyException(message)
{
cout<<"MyExceptionD..."<<endl;
}
MyExceptionD(constMyExceptionD&other)
:MyException(other)
{
cout<<"CopyMyExceptionD..."<<endl;
}
~MyExceptionD()
{
cout<<"~MyExceptionD..."<<endl;
}
};

intmain(void)
{
try
{
MyExceptionDe("testexception");
throwe;
}
catch(MyExceptionD&e)
{
cout<<"catchMyExceptionD..."<<endl;
cout<<e.what()<<endl;
}
catch(MyException&e)
{
cout<<"catchMyException..."<<endl;
cout<<e.what()<<endl;
}

return0;
}


派生类的异常能够被基类所捕获,且前面的异常处理程序能够匹配的话首先catch,如果把基类的放在前面,而且不是引用的形式,如catch(MyException e); 那么将会被这个所catch 到,而且在构造e 的过程会有object slicing 的问题。


二、异常与指针

抛出指针通常是一个坏主意,因为抛出指针要求在对应处理代码存在的任意地方都存在指针所指向的对象(注意此时throw抛出时复制的是指针本身,不会去复制指针指向的内容)

C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
intmain(void)
{
try
{
//MyExceptionDe("testexception");
//throw&e;
thrownewMyExceptionD("testexception");
}
/*catch(void*e)
{
cout<<"catchvoid*..."<<endl;
cout<<((MyExceptionD*)e)->what()<<endl;
delete(MyExceptionD*)e;
}*/
catch(MyExceptionD*e)
{
cout<<"catchMyExceptionD..."<<endl;
cout<<e->what()<<endl;
deletee;
}
catch(MyException&e)
{
cout<<"catchMyException..."<<endl;
cout<<e.what()<<endl;
}

return0;
}


其中MyException, MyExeptionD类如上所示,现在MyExeptionD 对象是在堆上分配的,所以在catch 的时候还没释放,还可以访问到

e->what(); 但需要自己在catch 末尾delete e; 假设将throw new MyExceptionD("test exception"); 换成

MyExceptionD e("test exception");
throw &e;

即抛出局部对象的指针,由于在catch 时MyExeptionD 对象已经被析构了,所以访问不到e->what(); 即e是空悬指针。

还有一点是,任何类型的指针都能被void* 指针所捕获,如果将注释打开,那么由于排在前面,异常首先将被它所捕获。


三、异常规格说明

1、异常规格说明的目的是为了让函数使用者知道该函数可能抛出的异常有哪些。
可以在函数的声明中列出这个函数可能抛掷的所有异常类型。
例如:

void fun() throw(A,B,C,D);

2、若无异常接口声明,则此函数可以抛掷任何类型的异常。
3、不抛掷任何类型异常的函数声明如下:

void fun() throw();

C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
voidfun(intn)throw(int,MyException,MyExceptionD)
{
if(n==1)
{
throw1;
}
elseif(n==2)
{
throwMyException("testException");
}
elseif(n==3)
{
throwMyExceptionD("testExceptionD");
}

}

voidfun2()throw()
{

}

intmain(void)
{
try
{
fun(2);
}

catch(intn)
{
cout<<"catchint..."<<endl;
cout<<"n="<<n<<endl;
}
catch(MyExceptionD&e)
{
cout<<"catchMyExceptionD..."<<endl;
cout<<e.what()<<endl;
}
catch(MyException&e)
{
cout<<"catchMyException..."<<endl;
cout<<e.what()<<endl;
}

return0;
}


实际上编译会产生警告:

warning C4290: 忽略 C++ 异常规范,但指示函数不是 __declspec(nothrow)

就是说VC++编译器现在还不怎么支持异常规格说明,举个例子说,voidfun(intn)throw(int,MyException,MyExceptionD); 没有声明double 类型的异常,但在函数内throw 1.0; 在外部catch (double) 还是会成功。

类,但内部的实现都没有有效的代码,只是用来标识当前程序产生了哪种类型的异常而已。

参考:

C++ primer 第四版
Effective C++ 3rd
C++编程规范

优质内容筛选与推荐>>
1、JavaScript - 对象
2、POJ 1182 食物链(带权并查集)
3、js常用方法
4、购物车编写
5、runtime统计页面数据或者统计按钮的点击次数


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn