Sự cố không phải với typeid
. Vấn đề là nhìn thấy typeid
sẽ khuyến khích bạn viết điều này:
PolymorphicType *pType = ...;
if(typeid(*pType) == typeid(Derived1))
pType->Func1();
else if(typeid(*pType) == typeid(Derived2))
pType->Func2();
else if(typeid(*pType) == typeid(Derived3))
pType->Func3();
Đây là những gì chúng tôi gọi là "thực sự ngu ngốc". Đây là một cuộc gọi hàm ảo được thực hiện theo cách ít hợp lý nhất có thể. typeid
có khả năng lạm dụng khi được sử dụng để thay thế các hàm dynamic_cast
và virtual
.
Ví dụ này nghe có vẻ xa vời. Xét cho cùng, rõ ràng đây chỉ là một cuộc gọi ảo. Nhưng mã xấu thường phát triển từ con đường kháng cự ít nhất; tất cả những gì cần làm là để một người làm một số typeid() == typeid()
và hạt giống của mã này đã bắt đầu. Nói chung, nếu bạn đang trực tiếp sử dụng typeid
thường xuyên, tỷ lệ cược là rất tốt mà bạn đang làm một cái gì đó mà có thể được thực hiện tốt hơn với các cấu trúc ngôn ngữ khác.
typeid
là phương pháp khấu trừ loại đa hình của khu nghỉ dưỡng vừa qua.
Mọi việc sử dụng typeid
có sai không? Tất nhiên là không. boost::any
sẽ không thể có nếu không có nó. Vâng, nó sẽ là có thể, nhưng sẽ không an toàn hơn void*
. typeid
là những gì làm cho loại an toàn boost::any
loại tẩy xóa có thể. Có những cách sử dụng hợp pháp khác của nó.
Nhưng trong tỷ lệ mã vạch để sử dụng, tôi khuyên bạn nên có khoảng một trong 10.000 dòng mã, nhiều nhất. Ít hơn nhiều, và có thể bạn đang sử dụng sai.
Kiểm tra loại có chậm không?
Nói chung, lý do chính để gọi typeid
nằm trong mã templated (như trong boost::any
) hoặc khi bạn đang mong đợi một loại đa hình. Nếu loại được xác định tĩnh (ví dụ: một tên tệp hoặc giá trị của một loại không đa hình), thì bạn có thể mong đợi nó được thực hiện tại thời gian biên dịch.
Đó là các giá trị đa hình mà bạn nên quan tâm. Tôi đã nhìn thấy một thử nghiệm hiệu suất cho thấy rằng một số triển khai thực hiện typeid
thực hiện việc phân cấp lớp, do đó, thời gian cần để tìm loại là tỷ lệ thuận với số lớp giữa loại thực và loại đã cho. Mọi triển khai sẽ khác nhau, nhưng đó là một dấu hiệu khá tốt có thể bạn không nên đặt nó vào mã hiệu suất quan trọng.
Người đã nói thiết kế xấu ở đâu? –
@SethCarnegie Tôi đã nghe một số người nói nó trên SO, và cũng đọc nó trong một cuốn sách loại kiểm tra là thiết kế xấu, nhưng không có lý do đã được đưa ra. – xcrypt
Rằng họ không đưa ra lý do có lẽ là một dấu hiệu cho thấy tính hợp pháp của các yêu sách của họ. Một số người nói rằng nếu bạn đang làm rất nhiều loại kiểm tra, bạn nên refactor mã của bạn thành các cuộc gọi chức năng đa hình. Ví dụ, thay vì làm 'if (typeid (a) == atype) doa(); else if (typeid (a) == btype) dob(); else if (typeid (a) == ctype) doc(); 'bạn chỉ có thể làm' a-> doafunc(); 'và hàm ảo thích hợp sẽ được gọi cho kiểu thời gian chạy' a'. –