【问题标题】:C++ - A few questions about throwing exceptionsC++ - 关于抛出异常的几个问题
【发布时间】:2016-06-02 09:53:06
【问题描述】:

我有几个关于在 C++ 中引发异常的问题。 根据我对他们的了解...

可以从 main() 函数中抛出异常。任何可以在 main() 函数中抛出异常的代码块都应该被 try 和 catch 语句包围,如下所示

    void foo(//args) {
     if (...) {
      throw "Error reached";
     } ...

    int main() {
     ...
     try {
      //Code that can throw an excpetion
     } catch(const char* msg) (
      cerr << msg << endl;
     } 
     ...
    }

在上面的例子中,为什么 catch 的参数是 const char *。 C++ 不允许字符串吗?另外,是否可以抛出一个不是 const char * 的异常,比如 int?还是一个字符?

是否在 foo 中抛出异常,终止 foo 函数?

是否可以将 try 和 catch 语句与 throw 放在同一个函数中?

抱歉,这些是基本问题。 谢谢所以

【问题讨论】:

  • 抱歉,我的意思是说 foo “Error达到”中抛出的异常是字符串或 const char *,因为我认为这是我需要放入 catch声明作为参数。
  • 您可以编辑您的问题,而不是在 cmets 中提供勘误表。
  • @The_Questioner 在下面添加了一个示例,HTH。

标签: c++ exception


【解决方案1】:

为什么 catch 的参数是 const char *

因为您抛出了衰减为const char* 的字符串文字。简而言之,你抓住你扔的东西。

C++ 不允许字符串吗?

确实如此,但要捕获字符串,您需要首先抛出字符串。

是否可以抛出不是 const char * 的异常,

你可以扔任何东西。抛出特殊的异常类是个好主意,例如 std::exception 并从它派生。

是否在 foo 中抛出异常,终止 foo 函数?

是的,确实如此。

是否可以将 try 和 catch 语句与 throw 放在同一个函数中?

如果你愿意,你可以这样做。这样做是个好主意的情况并不多。

看来您需要一本好书并阅读有关异常的章节。同时this super-FAQ entry可能会帮助你/

【讨论】:

  • 谢谢。如果你不介意,我有一个后续问题。如果我抛出的任何字符串文字衰减为 const char*,那么我该如何抛出一个字符串?之后我会研究一些好的 C++ 书籍。
  • @The_Questioner throw std::string("some string");
  • throw "some string"s;!!
  • @PreferenceBean 但是这意味着您首先需要将命名空间std::literals::string_literals 纳入范围。
【解决方案2】:

你可以抛出任何类型的对象。

编辑:(希望我现在明白了) 您所做的是抛出一个 C 字符串,在本例中为 const char[13] 类型。 C 数组将衰减为指向其第一个元素的指针,在本例中为 const char* 类型的指针。

通常你想要做的是抛出一个预定义的异常对象。它们可以在标题 &lt;stdexcept&gt; 中找到,并且是从基类 std::exception派生。派生的异常类例如是std::logic_errorstd::range_errorstd::bad_alloc 等。

他们的构造函数接受一个字符串作为参数,所以你可以举例

throw std::logic_error{"Negative values not allowed."};

可以在如下的 catch 语句中访问此消息:

catch(std::exception &e) // capture reference to base class
{
    std::cout << e.what() << '\n'; // what() of derived is called, since virtual
}

如果捕获到异常,就会发生所谓的堆栈展开。然后,您可以在本地处理错误,或重新抛出异常。只有当一个异常被抛出并且从未被捕获时,std::terminate() 才被称为程序中止。

您可以将 try/catch 语句放在任何地方。但是,请记住术语“异常”的实际含义。使用简单的条件表达式if (n &lt; 0) break; 或类似的东西可以轻松处理的情况,不需要异常处理。特别是如果您可以现实地期望这种不需要的情况经常发生。那么它就不是什么“异常”了。

如果您决定使用异常来处理错误并且它们不能在本地处理,您可以在 main() 的开头和结尾放置 try/catch 子句。

由于您可以将 几个 catch 语句直接放在 try 语句之后,因此您可以开始处理更具体的错误,或者通过 catch(...) { //... } 简单地捕获 anything

这一切都被详细描述(包括在 whenwhen not 使用它的指针,在C++ FAQ

编辑:这是一个使用 try/catch 语句的示例。但是,捕获的不是异常对象,而是一个 int (errno)。只是为了表明,你真的可以扔/抓任何你喜欢的东西。让process_several_files() 成为嵌套在代码中某处的函数:

 std::vector<std::string> process_several_files(std::vector<std::string> const& files)
 {
      std::vector<std::string> contents{};
      contents.reserve(files.size()); // files contains file names from user input
      for (auto const& file : files)
      {
           try
           {
                contents.emplace_back(get_file_contents(file.c_str())); // A "C like" function. get_file_contents() will throw "errno", if a file does not exist
           }
           catch(int err)
           {
                std::cerr << "***Error while opening " << file << " : " << std::strerror(err) << "***\n";
                continue;                   // "scope" didn't change, just keep iterating!
           }
      }
      return contents;
 }

【讨论】:

  • 字符串文字不是char* 类型。也不是const char* 类型。
  • 在我发布它的第一秒就看到了。对不起。
  • 我在帖子历史记录(包括当前版本)中看不到任何正确识别字符串文字类型的修订。
  • 啊,好吧,我误会了。我的意思是 char 文字,甚至这可能也不正确。不过,C-String 应该没问题。希望这一次。
  • 句子“你所做的是抛出一个 C 字符串,它的类型是“const char*”。仍然不正确。 C 字符串是一个数组,而不是一个指针。
猜你喜欢
  • 2011-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-04
  • 2011-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多