捕捉异常而不必抛出

Raf*_*ssi 1 c++ delphi exception try-catch

我是C++的新手,我来自一个Delphi场景,在这个场景中,我能够捕获异常,甚至无需声明显式throw.看看这里:

#include<iostream>
#include<exception>

int main() {

 try {

  int c;
  std::cin >> c;

 } catch(...) {

  std::cerr << "Warning!" << std::endl;
  char xz; std::cin >> xz;
  return 1;

 }

 char z; std::cin >> z;
 return 0;

}

//I return 1 because UNIX OS cares about this, a return != 0 means that Huston we have a problem
Run Code Online (Sandbox Code Playgroud)

我已经看到一些异常(例如除零)不会被自动捕获,所以我必须自己创建一个throw将在我的try-block中捕获的肯定.

如果你看一下上面的代码,当我第一次输入6.7或者test我应该能够在输出上看到warning!,但什么都没有.我在Windows 10机器上运行.

我知道这catch(...)是一般的,并给我肯定的保护,但为什么不抓错了输入?


注意.我上面提到过Delphi,因为如果你看下面的代码,我就能发现错误.

try

 a := StrToInt('6.78');              //conversion error [string->double], a is int
 ShowMessage('a is ' + a.ToString);

except
 on E: Exception do

 ShowMessage('Warning! > ' + e.Message);
 //^ raises "Warning! > '6.78' is not a valid integer value."

end;
Run Code Online (Sandbox Code Playgroud)

为什么我不能用C++产生相同的效果?我知道它们是两种不同的语言,但起初我会说德尔福更好地"对待"异常.例如,它会自动捕获除以零(见下文),而c ++不会.

//this raises the "Division by zero" error.
a := 8 div StrToInt('0');
Run Code Online (Sandbox Code Playgroud)

结论.所以问题是:我try-catch是否正确地声明了C++ ?我是否总是必须使用throw确保错误将被捕获或我可以省略它一些?

Sla*_*ica 9

文档中所述,您需要设置异常掩码std::cin以使其抛出std::ios_base::failure:

#include <iostream>

int main() {
    std::cin.exceptions( std::ios::failbit );
    try {
       int i = 0;
       std::cin >> i;
       std::cout << "i=" << i << std::endl;
    }
    catch(...) {
        std::cerr << "error!" << std::endl;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

实例

我是否总是必须使用throw以确保错误将被捕获或我可以省略它一些?

是的,您需要调用异常throw.虽然库可能会因为错误条件(包括标准条件)而调用throw,但它可能抛出什么异常以及何时应该在文档中说明.


tam*_*bre 8

std::cin 当用户输入无效类型时,不会抛出.

假设C++ 11及更高版本,行为如下:

如果提取失败,则将零写入值并设置failbit.如果提取导致值太大或太小而不适合值,则写入std :: numeric_limits :: max()或std :: numeric_limits :: min()并设置failbit标志.

来自std::basic_istream::operator>>.

要检查输入是否无效,您应该执行以下操作:

#include <cstdint>
#include <iostream>

std::int32_t main()
{
    std::int32_t example;
    std::cin >> example;

    if (std::cin.fail())
    {
        std::cout << "Invalid input" << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

或者您也可以这样做:

#include <cstdint>
#include <iostream>

std::int32_t main()
{
    std::int32_t example;

    if (!(std::cin >> example))
    {
        std::cout << "Invalid input" << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)