2012-02-04 29 views
9

At a reply of a blog post of Raymond Chen,Tại sao điều quan trọng là sử dụng static_cast thay vì reinterpret_cast ở đây?

Một người hỏi chỉ ra

Raymond, tôi tin rằng C++ ví dụ là không đúng bởi vì vị trí của subobject lớp cơ sở trong lớp dẫn xuất là không xác định theo ISO C++ 2003 Standard (10-3, trang 168), và bạn giả định rằng lớp con cơ sở luôn luôn ở đầu. Ví dụ C cũng sẽ ổn trong C++, vì vậy tôi sẽ gắn bó với nó.

Raymond trả lời

[Mã này không làm cho giả thuyết này. Đó là lý do tại sao điều quan trọng là sử dụng static_cast thay vì reinterpret_cast. Hãy thử: Thêm một phương thức ảo để BAO GIỜ (vì vậy vtable đi trước) và quan sát những gì trình biên dịch thực hiện. -Raymond]

Tôi có thể đoán sau khi đọc nhận xét của anh ấy. Sử dụng static_cast là tốt tại ví dụ nhưng reinterpret_cast là không. Bởi vì reinterpret_cast không chuyển đổi vtable. Tôi có hiểu nó đúng không?
Mặc dù, nếu tôi sử dụng C-Style cast tại đó (không reinterpret_cast), nó có thể cũng đi sai?

Tôi đọc lại lời giải thích diễn xuất của C++ hiệu quả hơn để hiểu điều đó. Nhưng không có câu trả lời về điều đó.

+2

Tôi không hoàn toàn thông thạo C++, nhưng sự hiểu biết của tôi là "diễn giải lại" nghĩa là '* (destination_type *) &' có nghĩa là trong C. Có lẽ "tĩnh cast" thực sự có mối quan hệ lớp và cho phép trình biên dịch thực hiện công việc chuyển đổi không tầm thường. –

Trả lời

17

Sử dụng static_cast là tốt tại ví dụ nhưng reinterpret_cast thì không. Bởi vì reinterpret_cast không chuyển đổi vtable.

Không, vấn đề là reinterpret_cast hoàn toàn không biết gì về di sản thừa kế. Nó sẽ chỉ trả về cùng một địa chỉ không thay đổi . Nhưng static_castbiết rằng bạn đang thực hiện downcast: tức là truyền từ lớp cơ sở sang lớp dẫn xuất. Vì nó biết cả hai loại liên quan, nó điều chỉnh địa chỉ tương ứng, tức là, làm điều đúng.

Hãy giả vờ thực hiện của chúng tôi đưa ra các giả thuyết lớp OVERLAPPEDEX có một hàm ảo như thế này:

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

Con trỏ chúng tôi đang đưa ra điểm đến OVERLAPPED subobject. reinterpret_cast sẽ không thay đổi điều đó. Nó sẽ chỉ thay đổi kiểu. Rõ ràng, việc truy cập vào lớp OVERLAPPEDEX thông qua địa chỉ này sẽ dễ dàng tàn phá, bởi vì các vị trí của các lớp con của nó là tất cả sai rồi!

 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_castbiết rằng để chuyển đổi một OVERLAPPED*-OVERLAPPEDEX* nó phải điều chỉnh địa chỉ, và làm điều đúng đắn:

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

Mặc dù, nếu tôi sử dụng C-Style đúc tại đó (không reinterpret_cast), nó có thể cũng đi sai?

Một C-style cast được định nghĩa là người đầu tiên trong các thứ sau đó thành công:

  1. const_cast
  2. static_cast
  3. static_cast, sau đó const_cast
  4. reinterpret_cast
  5. reinterpret_cast, sau đó const_cast

Như bạn có thể thấy, static_cast được thử trước reinterpret_cast, vì vậy trong trường hợp này, dàn diễn viên kiểu C cũng sẽ làm điều đúng.


More info


Không đảm bảo. Có rất ít sự bảo đảm về những gì xảy ra trên reinterpret_cast. Tất cả các triển khai mà tôi biết sẽ chỉ cung cấp cùng một địa chỉ không thay đổi.

+0

Vâng, 'chuyển đổi vtable' của tôi là một câu rất lạ. btw, C-style caster cũng biết mối quan hệ kế thừa? Có lẽ nó không phải là. Nhưng tôi đã luôn sử dụng dàn diễn viên kiểu C, ngay cả khi tôi sử dụng C++. Và tôi nghĩ nó thậm chí còn hoạt động tốt ở ví dụ này. Đó là điều kỳ lạ. – Benjamin

+1

@Benjamin Tôi đã thêm giải thích về phôi kiểu C và tại sao nó hoạt động trong trường hợp này. Tôi khuyên bạn nên sử dụng chúng mặc dù, bởi vì nó không phải là luôn luôn rõ ràng mà các lựa chọn thay thế được chọn. Một trường hợp kiểu C là một cái búa rất cùn. –

+0

Tất nhiên tôi sẽ làm theo đề nghị của bạn, bởi vì tôi hiểu nó ngay bây giờ. Cảm ơn bạn. Thứ tự của C-Style caster của bạn có được chuẩn hóa không? – Benjamin

Các vấn đề liên quan