Generics في C++: لماذا هي ضرورية وكيفية استخدامها للمبتدئين

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

Generics في C++: لماذا هي ضرورية وكيفية استخدامها

\n\n

كل مبرمج عاجلاً أم آجلاً يواجه موقفاً يحتاج فيه إلى كتابة دالة تعمل مع أنواع بيانات مختلفة. على سبيل المثال، دالة إيجاد العنصر الأقصى – يجب أن تعمل بشكل جيد مع int و double و string. بدون أدوات خاصة، سيكون عليك كتابة تطبيق منفصل لكل نوع. هنا تأتي generics (الأنواع العامة) أو كما تسمى في C++، القوالب لمساعدتك.

\n\n

في C++، آلية القوالب هي أساس البرمجة العامة. تتيح لك كتابة كود يعمل مع أي نوع بيانات دون التضحية بالأداء. في هذه المقالة، سنشرح ما هي generics في C++، ولماذا هي ضرورية وكيفية استخدامها عملياً. المادة موجهة للمبتدئين، لذا سننتقل من البسيط إلى المعقد.

\n\n

ما هي القوالب (generics) في C++؟

\n\n

القالب (template) هو بناء يسمح بتعريف دالة أو كلاس يعمل مع نوع بيانات عشوائي. بدلاً من نوع محدد، تحدد معامل النوع (مثل T)، ويقوم المترجم عند الترجمة باستبدال النوع المطلوب. وهذا يسمى استنساخ القالب.

\n\n

تخيل قالباً لصنع البسكويت. القالب واحد، لكن يمكن صنع البسكويت من عجائن مختلفة: رملية، شوكولاتة، شوفان. القالب هو الشكل، والنوع (int, double, string) هو العجين. تصف الخوارزمية مرة واحدة، ويقوم المترجم تلقائياً بإنشاء إصدارات للأنواع المطلوبة.

\n\n

هناك نوعان من القوالب:

\n
    \n
  • قوالب الدوال – لإنشاء دوال عامة.
  • \n
  • قوالب الكلاسات – لإنشاء كلاسات عامة (مثل الحاويات).
  • \n
\n\n

قوالب الدوال: الخطوة الأولى نحو الكود العام

\n\n

لنبدأ بأبسط شيء – دالة قالبية. لنفترض أننا بحاجة إلى دالة تعيد القيمة القصوى من قيمتين. إليك كيف تبدو بدون قوالب:

\n\n
int max_int(int a, int b) {\n    return (a > b) ? a : b;\n}\n\ndouble max_double(double a, double b) {\n    return (a > b) ? a : b;\n}
\n\n

الكود مكرر. مع القالب يتم حل ذلك بأناقة:

\n\n
#include <iostream>\n#include <string>\n\ntemplate <typename T>\nT max_value(T a, T b) {\n    return (a > b) ? a : b;\n}\n\nint main() {\n    std::cout << max_value(10, 20) << std::endl;           // 20\n    std::cout << max_value(3.14, 2.71) << std::endl;       // 3.14\n    std::cout << max_value(std::string("apple"), \n                             std::string("banana")) << std::endl; // banana\n    return 0;\n}
\n\n

الكلمة المفتاحية template تخبر المترجم أن هذا قالب. <typename T> هي قائمة معاملات القالب. T هو اسم نوع افتراضي سيتم استبداله لاحقاً. بدلاً من typename يمكن استخدام class – لا فرق:

\n\n
template <class T>\nT max_value(T a, T b) {\n    return (a > b) ? a : b;\n}
\n\n

عند استدعاء max_value(10, 20)، يرى المترجم أن الوسائط من نوع int، ويقوم تلقائياً بإنشاء إصدار من الدالة لـ int. هذه العملية تسمى استنتاج الأنواع. إذا لزم الأمر، يمكن تحديد النوع صراحة:

\n\n
std::cout << max_value<double>(5, 7.5) << std::endl; // 7.5
\n\n

هام: يجب تعريف الدالة القالبية في ملف الرأس (أو قبل استخدامها)، لأن المترجم يحتاج إلى رؤية التعريف الكامل للاستنساخ.

\n\n

قوالب الكلاسات: إنشاء حاويات عالمية

\n\n

قوالب الكلاسات هي أداة أكثر قوة. المثال الأبرز هو الحاويات من المكتبة القياسية (STL): std::vector<int>، st

المدونات

توصيات الكتب