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子句会