异常处理和强制转换
Exception handling and coercion
try
{
throw Derived();
}
catch (Base&)
{
std::cout << "subtypingn";
}
try
{
throw "lol";
}
catch (std::string)
{
std::cout << "coercionn";
}
输出:subtyping
terminate called after throwing an instance of 'char const*'
为什么异常处理可以很好地处理子类型,而不能处理强制转换?
捕捉抛出的异常与向函数传递参数有很大不同。有相似之处,但也有细微的差别。
- 异常总是至少复制一次(根本不可能避免)
-
catch
子句按其声明的顺序进行检查(不是最合适的) -
它们的类型转换形式较少:
- 基于继承coversions,
- 从类型化指针到非类型化指针的转换(
const void*
捕获任何指针)
不允许任何其他类型的转换(例如,int
到double
,或隐式const char*
到string
-您的示例)。
关于你在评论中的问题假设存在层次结构:
class Base {};
class Derived: public Base {};
class Base2 {};
class Leaf: public Derived, public Base2 {};
现在根据catch
子句的顺序,一个合适的块将被执行。
try {
cout << "Trying ..." << endl;
throw Leaf();
} catch (Base& b) {
cout << "In Base&";
} catch (Base2& m) {
cout << "In Base2&"; //unreachable due to Base&
} catch (Derived& d) {
cout << "In Derived&"; // unreachable due to Base& and Base2&
}
如果你切换Base
和Base2
的捕获顺序,你会注意到不同的行为。如果Leaf
从Base2
私有继承,那么catch Base2&
无论放在哪里都是不可访问的(假设我们抛出Leaf
)
一般来说很简单:顺序很重要
c++ 11标准第15.3/3段定义了处理程序匹配某个异常对象的确切条件,这些条件不允许用户定义的转换:
处理程序匹配
E
类型的异常对象,如果-处理程序的类型为
cv T
或cv T&
,并且E
和T
是相同的类型(忽略顶级cv
限定符),或者-处理程序的类型为
cv T
或cv T&
,并且T
是E
的一个明确的公共基类,或-处理程序的类型为
中的一个或两个处理程序cv1 T* cv2
,E
是指针类型,可以转换为对象的类型
一个标准的指针转换(4.10),不涉及到private或protected指针的转换或歧义类
资质转换
——处理程序是一个指针或指向成员类型的指针,
E
是std::nullptr_t
。[…)
相关文章:
- 为什么我应该在异常处理中使用std::cerr而不是std::cout
- 当我使用 C++ 中的 C# dll 来使用 Selenium 时,存在异常处理问题
- Firebase C++VS2018 SDL2-在Firebase::app::create(..)上执行异常处理
- 使用 stoi 功能进行异常处理
- 子系统中的异常处理:本机
- 与异常处理程序中的操作员<<不匹配
- 数组 C++ 上的异常处理程序
- 异常处理:如果用户输入不是三个特定字符之一
- C++ 异常处理错误输出
- 视觉 std::矢量无异常:警告 C4530:使用了C++异常处理程序,但未启用展开语义.指定 /EHsc
- C++交换机状态异常处理
- 在字符串类上的成员函数和out_of_range异常处理
- 奇怪的消息 (_Base_bitset::_M_do_to_ulong) 从溢出异常处理程序中打印出来
- 执行视觉工作室异常处理模式
- 为什么隐式转换在异常处理中从派生到基?
- C++执行期间的类成员函数错误/异常处理
- 从C‘goto’错误处理范式到C++异常处理范式的转换
- 将异常处理从 python 转换为 C++
- 异常处理和强制转换
- 类型转换和异常处理