كيف تجتاز مقابلة C++: أهم الأسئلة من الألف إلى الياء
\n\nمقابلة منصب مطور C++ هي اختبار ليس فقط لمعرفة بناء الجملة، بل وأيضًا للفهم العميق لعمل المترجم، وإدارة الذاكرة، وخصائص البرمجة كائنية التوجه. في هذه المقالة، قمنا بتحليل أهم الأسئلة من الألف إلى الياء التي تُطرح غالبًا في المقابلات. ستكون المادة مفيدة لكل من مطوري المستوى المبتدئ (junior) وأولئك الذين يستعدون للمستوى المتوسط (middle).
\n\n1. أساسيات بناء الجملة وأنواع البيانات
\n\nلنبدأ بالأساسيات — الأسئلة التي تختبر فهمك للمفاهيم الأساسية في C++.
\n\n1.1. ما الفرق بين المرجع (reference) والمؤشر (pointer)؟
\nهذا سؤال كلاسيكي. الاختلافات الرئيسية:
\n- \n
- المرجع لا يمكن أن يكون
nullptr، بينما المؤشر يمكن. \n - لا يمكن إعادة ربط المرجع بكائن آخر بعد التهيئة. \n
- المؤشر يدعم العمليات الحسابية، بينما المرجع لا يدعمها. \n
int a = 5;\nint& ref = a; // مرجع\nint* ptr = &a; // مؤشر\n\nref = 10; // a = 10\n*ptr = 20; // a = 20\n\n\n1.2. ما هو const وكيفية استخدامه بشكل صحيح؟
\nيُستخدم const في C++ لحماية البيانات من التغيير. من المهم التمييز بين const قبل النوع وبعده:
- \n
const int* ptr— مؤشر إلى عدد صحيح ثابت (لا يمكن تغيير القيمة في العنوان). \nint* const ptr— مؤشر ثابت إلى عدد صحيح (لا يمكن تغيير العنوان). \n
2. البرمجة كائنية التوجه (OOP)
\n\nأسئلة OOP هي جزء إلزامي من مقابلة C++. دعنا نحلل الموضوعات الرئيسية.
\n\n2.1. الدوال الافتراضية (Virtual Functions) وتعدد الأشكال (Polymorphism)
\nتوفر الدوال الافتراضية الربط المتأخر (تعدد الأشكال الديناميكي). مثال:
\n\nclass Base {\npublic:\n virtual void show() { std::cout << "Base\\n"; }\n virtual ~Base() = default;\n};\n\nclass Derived : public Base {\npublic:\n void show() override { std::cout << "Derived\\n"; }\n};\n\nint main() {\n Base* b = new Derived();\n b->show(); // سيطبع "Derived"\n delete b;\n}\n\n\nمن المهم تذكر المُدمّر الافتراضي (virtual destructor) — بدونه، عند حذف كائن عبر مؤشر للفئة الأساسية، سيتم استدعاء مُدمّر الفئة الأساسية فقط، مما يؤدي إلى تسرب الذاكرة.
\n\n2.2. الدوال الافتراضية البحتة (Pure Virtual Functions) والفئات المجردة (Abstract Classes)
\nالفئة التي تحتوي على دالة افتراضية بحتة واحدة على الأقل (= 0) تصبح مجردة. لا يمكن إنشاء مثيل لهذه الفئة — فقط فئة وارثة مع تنفيذ جميع الدوال الافتراضية البحتة.
2.3. ما هما vtable و vptr؟
\nلتنفيذ تعدد الأشكال، يقوم المترجم بإنشاء جدول افتراضي (vtable) لكل فئة تحتوي على دوال افتراضية. يحتوي كل كائن على مؤشر مخفي (vptr) إلى هذا الجدول. يتم استدعاء الدالة الافتراضية من خلال الوصول غير المباشر عبر vptr، مما يضيف تكاليف إضافية طفيفة.
\n\n3. إدارة الذاكرة والمؤشرات الذكية
\n\nتمنح C++ المطور تحكمًا كاملاً في الذاكرة، مما يتطلب عناية خاصة.
\n\n3.1. الفرق بين new/delete و malloc/free
\n- \n
mallocيخصص الذاكرة، لكنه لا يستدعي المُنشئ.freeيحرر الذاكرة دون استدعاء المُدمّر. \nnewيخصص الذاكرة ويستدعي المُنشئ.deleteيستدعي المُدمّر ويحرر الذاكرة. \n
3.2. المؤشرات الذكية: unique_ptr, shared_ptr, weak_ptr
\nتدير المؤشرات الذكية عمر الكائن تلقائيًا. النقاط الرئيسية:
\n- \n
std::unique_ptr— ملكية حصرية، لا يمكن نسخه، فقط نقله. \nstd::shared_ptr— ملكية مشتركة عبر عداد المراجع. \nstd::weak_ptr— لا يزيد عداد المراجع، و