0

我在 C++ 中遇到异常问题,涉及异常的结构以及参数的传递方式等等。

从这个页面:http ://www.cplusplus.com/doc/tutorial/exceptions/

1)当你扔东西时,例如:throw 20;,你是否传递20int e,如果是这样,如果你只通过输入一个给出屏幕的命令来响应,那么抛出一个整数有什么意义?

2)如果程序遇到异常并抛出一些东西,那么程序是否会去 catch 以修复程序中的问题,或者程序是否去 catch 只是为了响应发生了错误并且您需要修复它程序。

3)查看标准异常部分:底部显示的异常(bad_alloc, bad_cast, bad_exception,... 等)是否应该是可以传递给变量的异常类型?就像您说catch(bad_exception& e)的那样,唯一e可以接收的是不适合任何其他异常类型的数字/浮点数/字符?老实说,我对标准异常感到非常困惑。

4) 在标准异常中,又是exceptionsclass myexception: public exception构造函数中吗?

对不起,很长的帖子。非常感谢任何简化主题、建议或帮助的在线教程。谢谢 :)

4

1 回答 1

3

This answer might be above your level, but I hope it at least gives you a basic understanding of what happens when an exception is thrown. And it will give you some googleable terms at the very least.

A throw statement is not an immediate function call. It is a point in a program where a certain object is constructed (be it an int, std::exception, std::runtime_error, or any other type of object).

After the exception object is constucted, the stack is unwound. This is an important concept and I will try to sketch it in a few words. Unwinding the stack means all the functions you have called are traversed in reverse order, and all objects allocated (on the stack) in those functions are destructed. This process continues backwards until a catch block is reached that catches your type of exception (normal function overload resolution rules apply here, so conversions are possible).

An illustrative example:

#include <iostream>
#include <memory>
#include <string>

class my_exception
{
public:
  my_exception(const std::string& message) : message(message) {}
  const std::string& what() { return message; }
private:
  const std::string message;
};

void boo()
{
  int local = 5; // local, "automatic storage duration" variable
  throw my_exception("boo threw");
}
void bam()
{
  int* i = new int(42); // dynamically allocated int, unowned, accessible
  std::unique_ptr<int> j(new int(43)); // dynamically allocated int, owned by a smart pointer with automatic storage duration
  boo();
  delete i;
}

void f()
{
  try
  {
    bam();
  }
  catch(const my_exception& e)
  {
    std::cout << e.what();
  }
}

int main()
{
  f();
}

The process that perspires is the following:

  1. main is entered
  2. f() is called
  3. try block is entered
  4. bam() is called
  5. an int is dynamically allocated. A pointer to int named i with automatic storage duration is constructed (on the stack)
  6. a unique_ptr object containing a pointer to another dynamically allocated int is created.
  7. boo() is called
  8. An int with automatic storage duration in constructed.
  9. An object of type my_exception is constructed and stack unwinding begins.
  10. boo() is left, and local is destructed (cleaned up)
  11. we're back in bam() and also leaving it behind: first j's destructor is called, which calls delete on the integer with value 43. Then the pointer object i is destructed, but the integer it pointed to is not deleted. We have a memory leak (the delete i; statement is never reached).
  12. we're back in f(), where a friendly catch catches our my_exception and outputs the message though std::cout.

To answer your questions:

1) No, a more complex process happens, which eventually ends in step 12 which might resemble a function call, but it is not really.

2) See above.

3) A catch "receives" an object. It works much like function overloads. The best one is picked. If there is no match, unwinding continues. e doesn't "receive" anything. It might be constructed from whatever is thrown, but that requires that the type of e has the right conversion/constructor.

4) No. That specifies inheritance. Example:

#include <stdexcept>

class my_exception : public std::exception
{
public:
  my_exception(const std::string& message) : std::exception(message) {}
}

This my_exception class inherits the what() function defined in std::exception, so I don't need to define it myself.

于 2013-06-28T08:41:58.843 回答