【发布时间】:2019-08-24 10:08:14
【问题描述】:
对于这个问题,不应该涉及多态性,即没有虚拟方法,没有虚拟基类。以防万一,我的案子不涉及任何这些。
假设我有一个类Derived,它有一个明确的可访问父类Base,没有多态性(没有虚拟方法,没有虚拟基类),但可能涉及间接和/或多重继承。
进一步假设我有一个有效的指针Derived *derived
(指向Derived 类型的对象或其子类)。
在这种情况下,我相信static_cast<Base*>(derived) 是有效的
(产生一个有效的可用指针)。当Base 和Derived 之间的祖先链涉及多重继承时,此static_cast 可能意味着调整指针以在Base 实例中定位Derived 实例。为此,编译器需要知道继承链,在这种情况下他就是这样做的。但是,如果插入到void * 的中间转换,则该继承链信息对编译器隐藏。尽管如此,这样的静态转换对于哪个继承链有效?我期待以下情况之一:
- 根本没有?从 void 指针访问
static_cast是未定义的行为,除非指针确实指向确切的类型。 - 对于所有没有多重继承的链?然后,编译器可以保证
Base始终位于Derived的开头 - 但是标准是什么意思? - 对于在所有中间多重继承链的第一个父类中找到
Base的所有链?也许Base和Derived的开头仍然匹配? - 总是?
static_cast到 void 指针总是可以调整到第一个父级的开头,而static_cast从 void 指针撤消该调整。但是对于多重继承,“第一个父级”不一定是所有父级的父级。
【问题讨论】:
-
解决这个问题的常用方法是 CRTP(又名静态多态性)。那么使用
static_cast是安全的。 -
static_cast<Base*>(derived)即使存在虚方法也是有效的。但是static_cast<Base*>((void*)derived)已经错了,只有当基地址与派生地址相同时才给出正式正确的指针。 (假设即使 Derived 仅从 Base 继承,但 Base 没有虚函数,而 Derived 有它 - 地址会有所不同)。无论如何-尝试使用不正确的static_cast<Base*>((void*)derived)而不是正确的static_cast<Base*>(derived)? -
@RbMm:当中间
void*存储在我无法控制的某个地方时,可能需要进行此类转换。在这种情况下,它是std::experimental::coroutine_handle<>。我想知道是否可以在子类中实现分配/解除分配,将其传递给编译器生成的协程机制,然后只与基类交互。出于效率原因,我宁愿避免运行时多态。 -
intermediate
void*- 什么对象?如果您在编译时知道这一点 - 您需要先将void*转换为这种类型 -
这是 C++2a 协程中使用的
promise。在clang + libc++中,指针的实际路径大致是coroutine_handle = __builtin_coro_promise(std::addressof(promise),...,true),然后是promise = *static_cast<Promise*>(__builtin_coro_promise(coroutine_handle,...,false))。这两个调用本质上是在协程转换期间由编译器生成的。
标签: c++ inheritance static-cast upcasting