从继承的异常中抛出字符串异常 class
Throw string exception from inherited exception class
我实现了继承自 std::exception
的异常 class
,如下所示:
class MyException : public exception
{
public:
MyException(string exc)
{
this->exc = exc;
}
const char * what() const throw ()
{
return exc.c_str();
}
private:
string exc;
};
现在我手动抛出 MyException
并假设在我的 code
中发生了异常,但我在 catch
部分以两种不同的方式测试了它:
正常抓取catch (const std::exception exc)
try
{
throw MyException("This is an exception");
}
catch (const std::exception exc)
{
MessageBoxA(NULL, exc.what(), "", MB_OK);
}
抓取参考catch (const std::exception &exc)
try
{
throw MyException("This is an exception");
}
catch (const std::exception &exc)
{
MessageBoxA(NULL, exc.what(), "", MB_OK);
}
第一个抛出的异常字符串是:
Unknown exception
第二个抛出的异常(在 catch 部分有 &
的异常)是:
This is an exception
为什么我在没有引用(&
)的情况下正常使用 catch 时无法获得我的自定义异常 string,为什么是 OK参考?
您正在按值捕获 std::exception
,您的编译器调用了 std::exception
的复制构造函数,您的数据丢失了。
两者之一;
- 通过引用捕获您的异常,这不会导致复制。
或
- 直接抓
MyException
选项 2 仍然执行复制,这是多余的,所以我会选择选项 1。
这是所有多态性都有的限制,而不仅仅是例外。
当您通过引用捕获时,您捕获了对派生 class 的现有实例的引用,因此,您可以调用它们的虚拟方法。
当你按值捕获时(你永远不应该这样做,这是原因之一),你捕获了一个 std::exception
对象本身。因为 exception
不是抽象的,所以这当然会起作用。但是,您现在获得了一个类型为 std::exception
的新对象。因此,它从来没有 exc
成员,更重要的是,它没有您想要的 what
覆盖。相反,调用了 what
的原始定义,因为您从未初始化基本异常 - 打印 "Unknown exception"
.
您正在经历 object slicing。
当 value 接收派生实例作为其基础 class 时会发生这种情况——在您的情况下,按值捕获 std::exception
。您的派生 class' 成员在转换为基础 class.
的过程中被“切掉”
当您希望以多态方式使用参数时,通过指针或 (const) 引用接收总是更可取。要捕获 std::exception
,您应该始终通过 const 引用进行捕获(我真的想不出您 不会 的场景)。
我实现了继承自 std::exception
的异常 class
,如下所示:
class MyException : public exception
{
public:
MyException(string exc)
{
this->exc = exc;
}
const char * what() const throw ()
{
return exc.c_str();
}
private:
string exc;
};
现在我手动抛出 MyException
并假设在我的 code
中发生了异常,但我在 catch
部分以两种不同的方式测试了它:
正常抓取
catch (const std::exception exc)
try { throw MyException("This is an exception"); } catch (const std::exception exc) { MessageBoxA(NULL, exc.what(), "", MB_OK); }
抓取参考
catch (const std::exception &exc)
try { throw MyException("This is an exception"); } catch (const std::exception &exc) { MessageBoxA(NULL, exc.what(), "", MB_OK); }
第一个抛出的异常字符串是:
Unknown exception
第二个抛出的异常(在 catch 部分有 &
的异常)是:
This is an exception
为什么我在没有引用(&
)的情况下正常使用 catch 时无法获得我的自定义异常 string,为什么是 OK参考?
您正在按值捕获 std::exception
,您的编译器调用了 std::exception
的复制构造函数,您的数据丢失了。
两者之一;
- 通过引用捕获您的异常,这不会导致复制。 或
- 直接抓
MyException
选项 2 仍然执行复制,这是多余的,所以我会选择选项 1。
这是所有多态性都有的限制,而不仅仅是例外。
当您通过引用捕获时,您捕获了对派生 class 的现有实例的引用,因此,您可以调用它们的虚拟方法。
当你按值捕获时(你永远不应该这样做,这是原因之一),你捕获了一个 std::exception
对象本身。因为 exception
不是抽象的,所以这当然会起作用。但是,您现在获得了一个类型为 std::exception
的新对象。因此,它从来没有 exc
成员,更重要的是,它没有您想要的 what
覆盖。相反,调用了 what
的原始定义,因为您从未初始化基本异常 - 打印 "Unknown exception"
.
您正在经历 object slicing。
当 value 接收派生实例作为其基础 class 时会发生这种情况——在您的情况下,按值捕获 std::exception
。您的派生 class' 成员在转换为基础 class.
当您希望以多态方式使用参数时,通过指针或 (const) 引用接收总是更可取。要捕获 std::exception
,您应该始终通过 const 引用进行捕获(我真的想不出您 不会 的场景)。