2013-04-29 31 views
5

Tôi đã đọc một số chủ đề khác trên trang web này, và chúng đề cập đến cách dynamic_cast và static_cast đều an toàn cho upcasting.Casting - Tại sao tôi nên làm điều đó cho Upcasting

Tại sao những yêu cầu này lại được yêu cầu cho upcasting?

Ví dụ, nếu lớp B có nguồn gốc từ A, sau đó

A * ptr = new B(); 

vẫn hoạt động, và cư xử như một đối tượng của loại A. (Tôi cũng từ một nền tảng Java, nơi chuyển đổi cho upcasting là không cần thiết.

tôi cũng đọc trên trang web này mà dynamic_cast là không cần thiết cho downcasting [trong câu hỏi "When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?"] . Một lần nữa, tôi sẽ nghĩ rằng đúc là chỉ thực sự cần thiết khi bạn đang downcasting từ upcasting xảy ra tự động.

Tôi đang ở đâu sai?

+0

Lưu ý: trong câu hỏi trước, một trong những câu trả lời cho biết "Bạn không cần phải sử dụng nó để cast xuống ...". Tuy nhiên, từ ngữ cảnh của câu đầy đủ, nghĩa là bạn không bị giới hạn chỉ sử dụng nó để truyền xuống. [Tôi đã chỉnh sửa câu trả lời đó để xóa sự mơ hồ.] –

Trả lời

3

Nếu bạn có phân cấp thừa kế phức tạp, hành vi upcast mặc định có thể không hoạt động. Hãy xem xét ví dụ:

struct A {}; 
struct B : A {}; 
struct C : A {}; 
struct D : B, C {}; 

Trong hệ thống cấp bậc mà một đối tượng kiểu D có hai cơ sở khác nhau của loại A. Chuyển đổi từ D* sang A* không rõ ràng. Đối với loại trường hợp, bạn có thể buộc phải trải qua một bước trung gian

A *p = static_cast<B*>(d); // Give me the 'A' subobject within 'B' 

Tương tự như vậy, nếu có một chức năng với nhiều quá tải mà có thể mất một trong hai cơ sở hoặc các loại có nguồn gốc và bạn cần phải gọi phiên bản lấy cơ sở loại (lưu ý: mã mùi ở đây!) sau đó bạn có thể sử dụng các diễn viên để trực tiếp quá tải độ phân giải. Một lần nữa, nếu bạn cần phải trực tiếp giải quyết quá tải, bạn có thể làm điều gì đó sai trái.

Ngoài các trường hợp góc (tức làkhi bị ném lên trời mặc định không hoạt động) có thực sự là không có lý do để sử dụng một cách rõ ràng hoạt động diễn viên, và tôi sẽ thực sự tư vấn chống lại nó, như phôi phải là một ánh sáng cảnh báo và lạm dụng chúng có thể làm cho họ bình thường và không nâng báo động khi đọc mã.

+1

Tốt trường hợp góc dụ nhưng tôi muốn đặt câu hỏi về tính phù hợp thực tiễn của nó vì đây là mã xấu mà không bao giờ nên xảy ra ở cơ sở mã của bạn anyway (kim cương của cái chết) - ít nhất là trong sự kết hợp với một bị ném lên trời. –

0

Tại sao những yêu cầu này lại được yêu cầu cho upcasting?

Họ không phải là, và sử dụng chúng cho upcasts là (IMHO) sai lệch: không có dàn diễn viên được yêu cầu vì một lý do: logic, một đối tượng lớp con là-một thể hiện của lớp cha.

Tóm lại, tôi sẽ không khuyến khích các chương trình phát sóng rõ ràng. Đối với những người khăng khăng rằng tôi đòi hỏi sự nhất quán ít nhất: sử dụng upcasts rõ ràng ở khắp mọi nơi, kể cả trong initialisations:

A * ptr{static_cast<A*>(new B)}; 

Hầu hết mọi người sẽ đồng ý rằng đây chỉ là ngớ ngẩn.

+0

Đó là những gì tôi nghĩ. Nhưng sau đó tại sao một câu trả lời với 673 upvotes nói "Bạn không cần phải sử dụng nó để cast xuống" về động phôi http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast- và-diễn giải lại-cast-be-được sử dụng. Không đăng bài trên chủ đề đó vì tôi nghĩ có cái gì đó sai lầm cơ bản với sự hiểu biết của tôi – user929404

+1

@ user929404 Bạn đang hiểu sai câu trả lời mà - thông điệp thực tế là rằng 'reinterpret_cast' nào * không chỉ * làm việc cho downcasts, nó cũng có thể thực hiện diễn viên khác . Tuy nhiên, bài đăng không nói gì về thực sự * có * để sử dụng nó cho các chương trình phát sóng (bình luận trực tuyến khác, tuy nhiên, * làm * khuyên điều này). –

1

Trong trường hợp đa thừa kế (Java thực sự không có), bạn có thể điều chỉnh con trỏ "this" của bạn. Trong trường hợp đó một reinterpret_cast không an toàn, đó là những gì họ đang cố gắng nhấn mạnh bằng cách nói rằng static_cast và dynamic_cast là an toàn.

Là một lưu ý nhỏ, trong một cuộc điều tra trong một codebase được chuyển sang Android-without-dynamic_cast, tôi đã tìm thấy 127 dynamic_casts, trong đó 122 không thực sự cần thiết. Đây là mã được viết bởi những người đã được OK rất thành thạo trong C++.

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