提问者指出
Raymond,I believe the C++ example is not correct since the position
of the base class subobject in the derived class is unspecified
according to ISO C++ 2003 Standard (10-3,page 168),and you assume
that the base class subobject is always at the beginning. The C
example would be fine in C++ too,so I’d stick with it.
雷蒙德回答
[The code does not make this assumption. That’s why it’s important to
use static_cast instead of reinterpret_cast. Try it: Add a virtual
method to OVERLAPPED (so a vtable goes in front) and observe what the
compiler does. -Raymond]
看完他的意见后,我可以猜到.在示例中使用static_cast很好,但reinterpret_cast不是.因为reinterpret_cast不转换vtable.我明白了吗?
虽然,如果我使用C风格的演员(不是reinterpret_cast),那也可能会出错?
我重读了更有效的C的演员说明,以了解这一点.但是没有答案.
解决方法
Using static_cast is fine at the example but reinterpret_cast is not. Because reinterpret_cast is not convert vtable.
不,问题是reinterpret_cast完全忘记了遗产.它将简单地返回相同的地址not1.但static_cast知道你正在执行一个downcast:即从基类转换为派生类.既然知道这两种类型,所以相应地调整地址,即做正确的事情.
假设我们的实现规定了假设的OVERLAPPEDEX类,它具有如下虚拟函数:
+------+------------+------------------+-------------+ | vptr | OVERLAPPED | AssociatedClient | ClientState | +------+------------+------------------+-------------+ ^ | ptr
我们给出的指针指向OVERLAPPED子对象. reinterpret_cast不会改变.它只会改变类型.显然,通过这个地址访问OVERLAPPEDEX类很容易造成破坏,因为它的子对象的位置现在都是错误的!
what we believe we have when we access OVERLAPPEDEX through the pointer +------+------------+------------------+-------------+ | vptr | OVERLAPPED | AssociatedClient | ClientState | +------+------+-----+------+-----------+------+------+------+ | vptr | OVERLAPPED | AssociatedClient | ClientState | <- what we actually have +------+------------+------------------+-------------+ ^ | ptr
static_cast知道要将OVERLAPPED *转换为OVERLAPPEDEX *,它必须调整地址,并做正确的事情:
+------+------------+------------------+-------------+ | vptr | OVERLAPPED | AssociatedClient | ClientState | +------+------------+------------------+-------------+ ^ | ptr after static_cast
Though,if I use C-Style cast at there(not reinterpret_cast),could it also go wrong?
C风格的演员被定义为成功的第一个:
> const_cast
> static_cast
> static_cast,然后是const_cast
> reinterpret_cast
> reinterpret_cast,然后是const_cast
正如你所看到的,static_cast在reinterpret_cast之前尝试过,所以在这种情况下,C风格的演员也会做正确的事情.
没有保证.对于reinterpret_cast会发生什么,几乎没有什么保证.我知道的所有实现将简单地发出相同的地址不变.