Gần đây tôi đã làm việc trên một đoạn mã C++ cho một dự án phụ (cpp-markdown
library, cho tò mò), và chạy vào một câu hỏi mã hóa mà tôi muốn một số ý kiến.Tránh dynamic_cast/RTTI
cpp-markdown
có một lớp cơ sở được gọi là Token
, có một số lớp con. Hai trong số các lớp con chính là Container
(chứa các bộ sưu tập khác Token
s) và TextHolder
(được sử dụng làm lớp cơ sở cho Token
s có chứa văn bản, tất nhiên).
Hầu hết quá trình xử lý được xử lý qua chức năng ảo, nhưng một số xử lý được xử lý tốt hơn trong một hàm duy nhất. Đối với điều đó, tôi đã sử dụng dynamic_cast
để giảm con trỏ từ một số Token*
sang một trong các lớp con của nó, vì vậy tôi có thể gọi các hàm dành riêng cho lớp con và các lớp con của nó. Không có cơ hội đúc sẽ thất bại, bởi vì mã có thể cho biết khi một điều như vậy là cần thiết thông qua các chức năng ảo (chẳng hạn như isUnmatchedOpenMarker
).
Có hai cách khác tôi có thể thấy để xử lý này:
Tạo tất cả trong những chức năng mà tôi muốn gọi là chức năng ảo của
Token
, và chỉ để lại cho họ một cơ thể trống cho mỗi phân lớp ngoại trừ một (các) phân loại cần xử lý chúng, hoặc ...Tạo hàm ảo trong
Token
sẽ trả về con trỏ được nhập đúng cáchthis
khi được gọi trên một số kiểu con nhất định và con trỏ rỗng nếu được gọi trên bất cứ thứ gì khác. Về cơ bản một phần mở rộng của hệ thống chức năng ảo mà tôi đã sử dụng ở đó.
Phương pháp thứ hai có vẻ tốt hơn cả phương pháp hiện tại và phương pháp đầu tiên, với tôi. Nhưng tôi muốn biết các quan điểm của các nhà phát triển C++ có kinh nghiệm khác về nó. Hay tôi lo lắng quá nhiều về tầm thường. :-)
Đồng ý, nếu bạn đã kiểm tra loại có chức năng ảo, thì dynamic_cast là vô dụng. Cả hai giải pháp khác của bạn chỉ là màu trắng mà hệ thống phân cấp của bạn bị hỏng. Nếu bạn sẽ có một hack, ít nhất là sử dụng hack nhanh hơn. – BigSandwich
static_cast sẽ không hoạt động nếu lớp dẫn xuất sử dụng thừa kế ảo để kế thừa từ Mã thông báo. dynamic_cast sẽ không vô ích trong trường hợp này. – bk1e