2011-09-27 54 views
8

我能做到这一点,没有任何问题:为什么的try ... catch需要确切类型抛出

long lngval = 3L; 
int i = lngval; 

但如果我试试这个:

try { 
    throw 3L; 
} 

catch(int i) { 
    cout << "caught " << i << endl; 
} 

我得到一个未处理的异常。

这似乎不一致。在这种情况下没有类型转换的原因是什么?

+6

发表100次:“我只会抛出派生自std :: exception的对象” –

+1

@Tadeusz除了抛出一个'int'来终止一个程序的常见习语之外。 ('main'包含'try ... catch'来捕获int并返回它,这个习惯用法和调用'exit' **的效果相同,除了调用了所有局部变量的析构函数。 –

+0

@JamesKanze:有趣的是,我不知道这个成语。我确实看到了一种从无到有继承的“SuicideException”,一次,我会猜你的角色。在这两种情况下,尽管你确实没有人写过“catch(...)”子句。 –

回答

7

在第一种情况下,编译器可以准确地知道你想要做什么:将long转换为int。在第二种情况下,编译器必须假设,你可能有这样的结构:

try { 
    try { 
    throw 3L; 
    } 
    catch (int i) { /* P */ } 
} 
catch (long l) { /* Q */ } 

的想法是,编译器无法知道是否有可能是一个catch (long l)潜伏在当前的上下文之外,所以它永远不会安全地选择第一个可能的转换。

这也是为什么它的共同抛出异常时,而不是随机的类型,如intlong使用类层次结构:它可以很容易地以这样的方式,编译器可以或多或少规范添加到您的异常处理程序确定你的意图(通过is-a关系)。

0

您可以在一个try-catch块中捕获多个类型。为了让编译器知道要抛出哪个catch块,它必须能够匹配确切的类型。或者它可以有一个默认的catch块 - catch (...) {},但是你将无法得到这种情况下抛出的值。

1

catch语句在给定类型的情况下捕获一个对象(或者标量变量),所以如果类型不匹配,它将传递给下一个catch语句(如果有的话)或默认的异常接收者。

就你而言,你可以有第二个catch语句捕获很长时间,也许在别的地方,所以你的catch语句不会捕获任何东西。

捕捉任何异常,只是使用捕捉(){} :)

单尖,更好的使用异常类,或者继承它适合你自己的需要:)

1

你也可以throw 3; - 没问题。

intlong是不同的类型。除了查看它们的类型之外,异常处理的一个优点是可以告诉异常(一个中央try块可以处理来自各个地方的各种异常/ try块可以处理某些类型的异常,让其他异常传播)。

此外,建议抛出其中一个标准异常或从其中一个类派生类。那么如果你只是想处理这个异常并且不关心这个特定的类型,那么你就可以只用catch (const std::exception&)

4

catch确实不是必然需要确切的类型。

使用从std::exception派生的例外(在<stdexcept>中找到)是常见的和良好的做法。原因是,你可以多形地捕捉,即你做而不是需要知道确切的类型(另见Difference: std::runtime_error vs std::exception()),并且我们有一个约定来处理这个。

无论您使用的标准(例如:std::range_error)提供者之一,或者如果没有适合您的问题[足够],专门std::exception

#include <stdexcept> 

class moores_law_stopped : public std::exception { 
public: 
    virtual ~moores_law_stopped() throw() {} 
    virtual const char *what() const throw() { 
     return "moores law stopped. duck under your table."; 
    } 
}; 



#include <iostream> 
int main() { 
    try { 
     throw moores_law_stopped(); 
    } catch (std::exception const &e) { 
     std::cerr << "oh oh: " << e.what() << std::endl; 
    } 
} 

输出:

oh oh: moores law stopped. duck under your table. 

的约定是通过引用或const引用来捕获的,这样就可以获得多态行为而不用担心object slicing