C++ 中的 Exception (> 中文翻译)

href="15Exceptionhandling.files/filelist.xml" rel="File-List" />

15 Exception handling [except]

1 Exception handling provides a way of transferring control and information from a point in the execution of a program to an exception handler associated with a point previously passed by the execution. A handler will be invoked only by a throw-expression invoked in code executed in the handler’s try block or in functions called from the handler’s try block .

 

 

try-block:

try compound-statement handler-seq

 

function-try-block:

try ctor-initializeropt function-body handler-seq

 

handler-seq:

handler handler-seqopt

 

handler:

catch ( exception-declaration ) compound-statement

 

exception-declaration:

type-specifier-seq declarator

type-specifier-seq abstract-declarator

type-specifier-seq

...

 

throw-expression:

throw assignment-expressionopt

 

A try-block is a statement (clause 6). A throw-expression is of type void. Code that executes a throwexpression is said to “throw an exception;” code that subsequently gets control is called a “handler.” [Note: within this clause “try block” is taken to mean both try-block and function-try-block. ]

 

2 A goto or switch statement shall not be used to transfer control into a try block or into a handler.

[Example:

void f() {

     goto l1; // Ill-formed

     goto l2; // Ill-formed

     try {

         goto l1; // OK

         goto l2; // Ill-formed

l1: ;

     } catch (...) {

l2: ;

         goto l1; // Ill-formed

         goto l2; // OK

     }

}

end example] A goto, break, return, or continue statement can be used to transfer control out of a try block or handler. When this happens, each variable declared in the try block will be destroyed in the context that directly contains its declaration. [Example:

lab: try {

     T1 t1;

     try {

         T2 t2;

         if (condition)

         {

              goto lab;

         }

     }

     catch(...)

     {

         /* handler 2 */

     }

}

catch(...)

{

     /* handler 1 */

}

Here, executing goto lab; will destroy first t2, then t1, assuming the condition does not declare a variable. Any exception raised while destroying t2 will result in executing handler 2; any exception raised while destroying t1 will result in executing handler 1. ]

 

3 A function-try-block associates a handler-seq with the ctor-initializer, if present, and the function-body. An exception thrown during the execution of the initializer expressions in the ctor-initializer or during the execution of the function-body transfers control to a handler in a function-try-block in the same way as an exception thrown during the execution of a try-block transfers control to other handlers. [Example:

 

int f(int);

class C {

     int i;

     double d;

public:

     C(int, double);

};

C::C(int ii, double id)

try

: i(f(ii)), d(id)

{

     // constructor function body

}

catch (...)

{

     // handles exceptions thrown from the ctor-initializer

     // and from the constructor function body

}—end example]

 

 

 

1.       通过异常处理机制,程序控制流可以从异常发生点直接跳转到异常处理模块。通过显示调用throw语句可以触发这样的跳转。Throw语句必须处于try模块中,或者位于try模块中被调用函数的函数体内。

 

( 此处略去异常处理的相关语法)

 

从整体的角度来看,try模块可以被看作是一个语句(请看下面的相关注解)throw表达式的返回类型是void类型。当我们调用throw语句产生一个异常时,我们称之为抛出一个异常。抛出异常后,程序控制流随后跳转所至的模块被称为异常处理模块[注意:此处的短语try模块既指普通的try模块,也包括函数try模块]

 

2.       我们不应该通过goto或者switch语句强行地将程序控制流跳转到 “try模块或者 异常处理模块中去。

[Example:

void f() {

     goto l1; // 糟糕的风格

     goto l2; // 糟糕的风格

     try {

         goto l1; // OK

         goto l2; // 糟糕的风格

l1: ;

     } catch (...) {

l2: ;

         goto l1; // 糟糕的风格

         goto l2; // OK

     }

}

end example]

      

不过,goto, break, return, 或者 continue 这些语句可以被用来跳出try模块或者是异常处理模块。一旦程序控制流跳出了try模块或者是异常处理模块,那么在这些模块中声明的局部变量都将被销毁(此处并没有按照英文原文翻译,请参考英文原文)

lab: try {

     T1 t1;

     try {

         T2 t2;

         if (condition)

         {

              goto lab;

         }

     }

     catch(...)

     {

         /* handler 2 */

     }

}

catch(...)

{

     /* handler 1 */

}

 

在上面的例子中,当我们执行goto lab语句之后, 变量t2首先被销毁,然后是变量 t1,这里我们假设 condition没有声明额外的变量。如果在销毁t2的时候发生了异常,程序将会跳转到 “handler 2” 模块;如果在销毁t1的时候出了异常,那么程序控制流就会跳转到handler 1 模块。

 

3 函数try模块既可以捕捉到函数体内发生的异常,也可以捕捉到构造函数初始化列表中产生的异常。当构造函数初始化列表或者函数体抛出一个异常时,程序控制流将会跳转到相应的异常处理模块中去,这和普通的try模块的程序控制流跳转过程是一样的。

 

[Example:

 

int f(int);

class C {

     int i;

     double d;

public:

     C(int, double);

};

C::C(int ii, double id)

try

: i(f(ii)), d(id)   // 构造函数的初始化列表

{

     // 构造函数的函数体

}

catch (...)

{

     // 如果 构造函数初始化列表 或者 函数体 抛出了一个异常

     // 程序控制流将会跳转到这里

}—end example]

 

 

 

 

相关注解:

l         C++标准中, try-block 的确被定义为一个statement。下面是相关的定义:

statement:

labeled-statement

expression-statement

compound-statement

selection-statement

iteration-statement

jump-statement

declaration-statement

try-block

 

l         X-seq is one or more X’s without intervening delimiters (e.g. declaration-seq is a sequence of declarations).通过上面的解释可以看出,handler-seq指的是一个或者多个连续的异常处理模块,中间不掺杂其他的语法单位。下面是多个连续的异常处理模块的例子:

 

catch(int &i )

{

}

catch(char *ch )

{

}

catch(...)

{

}

 

 

l         ctor-initializeropt 指的是构造函数初始化列表,下标opt意思是该项为可选项。下面给出的是一个构造函数的函数try模块 的范例。

 

class A

{

public:

     A()

     Try                       ç 请注意try关键字所处的位置,其位于右括号之后,初始化列表的 : 之前

         :

     _k(0)

     {

         // 构造函数,在这个例子中,我们什么也没有做

     }

     catch(...)

     {

     }

 

     int _k;

};

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值