dynamic_cast
التنزيل الآمن وقت التشغيل dynamic_cast
dynamic_cast يتحقّق فعليًا وقت التشغيل من نوع الكائن قبل التنزيل بتسلسل وراثي فيه تعدّد أشكال — يرجع nullptr أو يرمي استثناء عند الفشل بدل سلوك غير معرَّف.
على عكس static_cast، يستخدم dynamic_cast معلومات النوع وقت التشغيل (RTTI) للتأكّد أن الكائن المُشار إليه فعليًا من النوع المطلوب — لذا يتطلّب أن يملك الصنف الأساس دالة virtual واحدة على الأقل (عادة destructor افتراضي). مع المؤشّرات، فشل التحويل يُرجع nullptr بدل انهيار؛ مع المراجع، الفشل يرمي std::bad_cast لأنه لا يوجد مرجع فارغ يُرجعه بديلًا.
الصياغة
Derived* p = dynamic_cast<Derived*>(basePtr); Derived& r = dynamic_cast<Derived&>(baseRef); // يرمي bad_cast عند الفشل
📄 مثال
class Shape { public: virtual ~Shape() = default; };
class Circle : public Shape { public: void draw() {} };
void render(Shape* s) {
if (Circle* c = dynamic_cast<Circle*>(s)) {
c->draw(); // نجح فقط لو s يشير فعليًا لـ Circle
} else {
// c هنا nullptr — فشل التحويل بأمان
}
}أهم النقاط
| العنصر | الوظيفة |
|---|---|
| تنزيل مؤشّر | يُرجع nullptr عند الفشل — يجب فحص النتيجة قبل الاستخدام |
| تنزيل مرجع | يرمي std::bad_cast عند الفشل — يحتاج try/catch |
| يتطلّب virtual | الصنف الأساس يحتاج دالة افتراضية واحدة على الأقل، وإلا خطأ ترجمة |
💡 نصائح عملية
- استخدمه فقط لما تحتاج فعليًا معرفة النوع الحقيقي وقت التشغيل — لو ممكن تصميم الكود بدون تنزيل أصلًا (عبر virtual functions)، هذا أفضل غالبًا
- افحص دائمًا نتيجة تنزيل المؤشّر قبل استخدامها — النتيجة قد تكون nullptr بصمت
⚠️ أخطاء شائعة
- استخدامه على صنف أساس بلا أي دالة virtual — خطأ ترجمة لأن التحقّق يحتاج vtable
- استخدام نتيجة تنزيل مؤشّر مباشرة دون فحص nullptr أولًا — انهيار فوري عند الفشل
خصائص ذات صلة
🎓 تريد فهم الصورة الكاملة خطوة بخطوة؟ ابدأ من مسار CPP الكامل بالعربي.