CppCoreGuidelines E.15 抛出异常,以引用的方式从层级结构中捕获异常
06 August 2023
“Throw by value, catch exceptions from a hierarchy by reference”
理由
以值的方式抛出异常(非指针),然后通过引用捕获,会阻止复制过程,导致产生对象的切片副本。
错误例子
void f() { try { // ... throw new widget{}; // don't: throw by value not by raw pointer // ... } catch (base_class e) { // don't: might slice // ... } }
应该使用引用:
catch (base_class& e) { /* ... */ }
或者,最好用常量引用:
catch (const base_class& e) { /* ... */ }
大部分异常处理不会修改异常的值,所以,一般来说,我们建议使用 const
注意
对于小数值类型,可以以值的方式捕获,比如枚举类型。
注意
重新抛出捕获的异常,请使用 throw
,不要用 throw e;
。用 throw e;
会抛出 e
的一个副本。因为是复制操作,可能会由于类型不同,把原来的异常对象切片处理成 std::exception
。另外,还要注意,不要尝试在所有函数中,捕获所有异常,避免显式的 try/catch
操作。
强化
- 当一个类型有虚函数,然后以值的方式被异常捕获,标记之。
- 抛出原始指针的异常,标记之。