C++ 为什么要尝试…catch需要抛出确切的类型

C++ 为什么要尝试…catch需要抛出确切的类型,c++,exception-handling,C++,Exception Handling,我可以做到,没问题: long lngval = 3L; int i = lngval; 但如果我尝试这样做: try { throw 3L; } catch(int i) { cout << "caught " << i << endl; } 试试看{ 投掷3L; } 捕获(int i){ cout您可以在一个try-catch块中捕获多个类型。为了让编译器知道要抛出到哪个catch块,它必须能够匹配确切的类型。或者它可以有一个默认的catch

我可以做到,没问题:

long lngval = 3L;
int i = lngval;
但如果我尝试这样做:

try {
  throw 3L;
}

catch(int i) {
  cout << "caught " << i << endl;
}
试试看{
投掷3L;
}
捕获(int i){

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

catch语句捕获一个对象(在您的例子中是标量变量)给定其类型,因此如果类型不匹配,它将传递到下一个catch语句(如果有)或默认异常接收器

在您的例子中,您可以让第二个catch语句捕捉长的内容,或者在其他地方,这样您的catch语句就不会捕捉任何内容

要捕获任何异常,只需使用catch(){}:)


一个提示,最好使用异常类,或者根据自己的需要将其子类化:)

在第一种情况下,编译器可以准确地告诉您要做什么:将
长的
转换为
int
。在第二种情况下,编译器必须假设您可能有这样的构造:

try {
  try {
    throw 3L;
  }
  catch (int i) { /* P */ }
}
catch (long l) { /* Q */ }
其思想是,编译器永远无法知道是否有
catch(long l)
潜伏在当前上下文之外,因此只选择第一个可能的转换是不安全的


这也是为什么在抛出异常时通常使用类层次结构,而不是像
int
long
这样的随机类型:这样可以很容易地向异常处理程序添加或多或少的规范,编译器可以确定您的意图(通过关系).

您也可以
抛出3;
-没问题

int
long
是不同的类型。异常处理的一个优点是,您可以通过查看其类型来区分异常(一个中央try块可以处理来自不同位置的各种异常/try块可以处理某些类型的异常,让其他异常传播)

此外,建议抛出一个标准异常或从其中一个异常派生一个类。如果您只想处理异常,而不关心特定类型,则可以使用
catch(const std::exception&)

catch
不一定需要确切的类型

使用从
std::exception
(可在
中找到)派生的异常是一种常见且良好的做法。原因是您可以通过多态方式捕获异常,也就是说,您不需要知道确切的类型(另请参见),并且我们有一个处理该异常的约定

您可以使用标准提供的一种方法(例如,
std::range\u 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;
    }
}

约定是通过引用捕获或const引用,这样您就可以毫无恐惧地获得多态行为。

写100遍:“我将只抛出从std::exception派生的对象”@Tadeusz,除了抛出一个
int
终止程序的常见习惯用法。(
main
包含一个
try…catch
来捕获
int
并返回它。这个习惯用法与调用
exit
的效果相同,只是调用了所有局部变量的析构函数。)@JamesKanze:有趣的是,我不知道这个成语。我确实看到了一个从无到有的自杀例外,有一次,我想你会猜到这个角色。在这两种情况下,尽管你真的认为没有人写过一个
捕获(…)
clause.@JamesKanze:我听说过这个习惯用法,但我认为它并不常见。如果你想半立即退出,那会是什么情况?如果你不能处理异常,就不要抓住它。如果你能抓住它,那么就抓住它。@phresnel我不知道这个习惯用法有多普遍,尽管我自己经常使用它。这是一个有效的例子,如果你不能处理异常,就不要抓住它我抛出了一个
int
(说实话,这是我能想到的唯一一个。)
oh oh: moores law stopped. duck under your table.