Why is it important to use static_cast instead of reinterpret_cast here?

前端 未结 1 815
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-02 08:36

At a reply of a blog post of Raymond Chen,

A questioner pointed out

Raymond, I believe the C++ example is not correct since the position of

1条回答
  •  Happy的楠姐
    2021-01-02 09:31

    Using static_cast is fine at the example but reinterpret_cast is not. Because reinterpret_cast is not convert vtable.

    No, the problem is that the reinterpret_cast is completely oblivious about the inheritance. It will simply return the same address unchanged1. But static_cast knows that you're performing a downcast: i.e. casting from a base class to a derived class. Since it knows both types involved it adjusts the address accordingly, i.e., does the right thing.

    Let's pretend our implementation lays out the hypothetical OVERLAPPEDEX class that has a virtual function like this:

    +------+------------+------------------+-------------+
    | vptr | OVERLAPPED | AssociatedClient | ClientState |
    +------+------------+------------------+-------------+
           ^
           |
          ptr
    

    The pointer we're given points to the OVERLAPPED subobject. reinterpret_cast would not change that. It would only change the type. Obviously, accessing the OVERLAPPEDEX class through this address would easily wreak havoc, because the locations of its subobjects are all wrong now!

           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 knows that to convert a OVERLAPPED* to OVERLAPPEDEX* it must adjust the address, and does the right thing:

     +------+------------+------------------+-------------+
     | 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?

    A C-style cast is defined as the first one of the following that succeeds:

    1. const_cast
    2. static_cast
    3. static_cast, then const_cast
    4. reinterpret_cast
    5. reinterpret_cast, then const_cast

    As you can see, a static_cast is tried before reinterpret_cast, so in this case, a C-style cast would also do the right thing.


    More info


    1Not guaranteed. There are very little guarantees about what happens on a reinterpret_cast. All implementations I know of will simply give out the same address unchanged.

    0 讨论(0)
提交回复
热议问题