C++ 例外情况下的类型转换
假设我有这个:C++ 例外情况下的类型转换,c++,C++,假设我有这个: namespace MyNamespace{ class Exception : public std::runtime_error { public: explicit Exception(const std::string &msg) : std::runtime_error(msg) {} }; } //namespace MyNamespace 我的程序中有一段代码: try{ foo(); } catch (const MyNamespace:
namespace MyNamespace{
class Exception : public std::runtime_error
{
public:
explicit Exception(const std::string &msg) : std::runtime_error(msg) {}
};
} //namespace MyNamespace
我的程序中有一段代码:
try{
foo();
}
catch (const MyNamespace::Exception &exc){
std::cout << exc.what();
}
试试看{
foo();
}
catch(const MyNamespace::Exception&exc){
std::cout你对1-4的回答是正确的,但背后的推理有点不正确
3) 这与explicit
关键字无关。throw
之后的表达式类型是const char[12]
,根据规则,抛出的异常类型是const char*
4) 同样,与显式
字符串构造函数无关。抛出的类型是std::string
,只有std::string
(带引用或不带引用)类型的处理程序才能捕获它
5) 很明显,没有
6) 当抛出异常时。您对1-4的回答是正确的,但背后的推理有点不正确
3) 这与explicit
关键字无关。throw
之后的表达式类型是const char[12]
,根据规则,抛出的异常类型是const char*
4) 同样,与显式
字符串构造函数无关。抛出的类型是std::string
,只有std::string
(带引用或不带引用)类型的处理程序才能捕获它
5) 很明显,没有
6) 当抛出异常时。您对3和4的解释是错误的,因此,您对5的回答也是错误的。原因如下:
当您捕获异常时,除了到基类的转换之外,不会执行任何转换。因此catch(Foo const&)
永远不会捕获可转换为Foo
的任何内容,除了Foo
的子类。正是由于这个原因,并且与显式的构造函数无关,您的代码不会捕获抛出的std::string
或char[]
你对3和4的解释是错误的,因此,你对5的回答也是错误的。原因如下:
当您捕获异常时,除了到基类的转换之外,不会执行任何转换。因此catch(Foo const&)
永远不会捕获可转换为Foo
的任何内容,除了Foo
的子类。正是由于这个原因,并且与显式的构造函数无关,您的代码不会捕获抛出的std::string
或char[] > 从3-5的措辞中,您显然认为C++试图将投掷< /代码>匹配到<代码> catch < /C>语句,就像它从重载函数中挑选出最佳匹配来调用。不是这样。<>代码>抛出语句被认为与任何代码> catch < /Cord>语句分开。实际上,您可以在编写捕获代码之前编译函数foo
及其throw
语句,因此它不能选择将std::string
转换为捕获代码最终寻找的某种类型……它可能不知道这一点
抛出的值的类型完全取决于要抛出的参数的类型,如果表达式在没有抛出的情况下出现,则可以在周围的上下文中理解。例如:
void foo()
{
...
throw XXX;
}
…抛出与…相同的类型
void foo()
{
...
auto what_will_be_thrown = XXX;
throw what_will_be_thrown;
}
捕获时不应用诸如const char*
到std::string
的转换,尽管可以通过公共基类(用于引用或指针)捕获派生类型,当然也可以使用const
引用等来捕获类型
Re 6)-无论值的类型如何,它都是在调用异常
构造函数之前创建的,就像任何其他函数调用的计时方式一样,但在这种情况下,被抛出的对象可以在与正常调用堆栈不同的单独内存区域中构造,这样它将在调用时发生的堆栈展开中幸存寻找匹配的catch语句。在编译器中编排的这个方法没有在标准中指定。< p>从3-5的措辞中,你显然认为C++试图将<代码>投掷< /代码>匹配到<代码> catch < /Cord>语句中,就像它从重载函数中挑选出最佳匹配来调用一样。事实并非如此。throw
语句与任何catch
语句是分开考虑的-实际上,您可以在编写捕捉代码之前编译函数foo
及其throw
语句,因此它不能选择将std::string
转换为某种类型。捕捉代码最终会失败国王……它可能不知道
抛出的值的类型完全取决于要抛出的参数的类型,如果表达式在没有抛出的情况下出现,则可以在周围的上下文中理解。例如:
void foo()
{
...
throw XXX;
}
…抛出与…相同的类型
void foo()
{
...
auto what_will_be_thrown = XXX;
throw what_will_be_thrown;
}
捕获时不应用诸如const char*
到std::string
的转换,尽管可以通过公共基类(用于引用或指针)捕获派生类型,当然也可以使用const
引用等来捕获类型
Re 6)-无论值的类型如何,它都是在调用异常
构造函数之前创建的,就像任何其他函数调用的计时方式一样,但在这种情况下,被抛出的对象可以在与正常调用堆栈不同的单独内存区域中构造,这样它将在调用时发生的堆栈展开中幸存正在寻找匹配的catch语句。但标准中没有具体说明编译器是如何编排的。谢谢你的回答,我现在就知道了。谢谢你的回答,我现在就知道了。谢谢你的回答,但我没有意识到第六个问题的答案:为什么在抛出异常而不是cougt时会创建它?我们说的是std::string吗?因为语言规范这么说。catch子句会