抛出静态类型的理由
Rationale for throwing static type?
根据c++ FAQ,当抛出一个对象时,它是使用表达式的静态类型抛出的。因此,如果您有:
catch ( some_exception const &e ) {
// ...
throw e; // throws static type, possibly causing "slicing"; should just "throw;" instead
}
和e
实际上是对源自some_exception
的某个类的引用,上面的throw
将导致对象被静默地"切片"。是的,我知道正确的答案是简单的throw;
,但是事情的方式似乎是一个不必要的混乱和bug的来源。
这样做的理由是什么?为什么不希望通过对象的动态类型抛出呢?
当您执行throw
时,从throw
的操作数构建临时对象,该临时对象是被捕获的对象。
c++没有内置支持基于表达式的动态类型复制内容或创建对象,因此临时对象是操作数的静态类型。
throw
的"参数"是一个表达式,它是表达式的类型,决定抛出的异常对象的类型。抛出的表达式的类型不一定是多态类型,因此可能没有办法确定表达式是否实际上引用了派生类型的基类子对象。
更简单的"表达式类型"规则还意味着实现不必在运行时动态确定异常对象的大小和类型,这可能需要为异常处理生成更复杂和更低效的代码。如果它必须这样做,它将表示语言中唯一需要调用点未知类型的复制构造函数的地方。这可能会大大增加实现成本。
考虑可以有对对象的引用,其中引用的静态类型是可复制的,但对象的动态类型不是。
struct foo {};
struct ncfoo : foo
{
private:
ncfoo(ncfoo const&) {}
};
ncfoo g_ncfoo;
void fun()
{
foo& ref = g_ncfoo;
throw ref; // what should be thrown here?
}
如果你说"in this case just throw the static type",那么确切的规则是什么——"in this case"是什么意思?我们刚刚捕获的引用在没有复制的情况下被"重新抛出",其他所有内容都被复制?嗯…
但是无论你如何定义规则,它仍然会令人困惑。根据引用抛出会导致不同的行为,这取决于我们从哪里获得引用。Neh。c++已经足够复杂和令人困惑了:)
相关文章:
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 是否有理由对非负常量使用无符号类型?
- 对于类型是类模板专业化的参数,ADL背后的理由是什么
- 类型特征的理由检查班级特殊功能的琐事
- 有没有理由不使用固定宽度类型
- C++11:是否有理由为什么某些常规类型不应该专门使用“std::hash”
- 是否有理由不使用单元强制类型
- 是否有理由显式声明模板类型
- 有什么理由在dll中定义类型吗?比如#define MODULE_NAME_INT8 __int8
- 抛出静态类型的理由