الأنواع العامة (Generics) في C++: لماذا هي ضرورية وكيفية استخدامها عمليًا

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

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

ابدأ الدورة

مقدمة: ما هي الأنواع العامة (Generics) في C++ ولماذا هي ضرورية

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

تتيح لك الأنواع العامة كتابة كود يعمل مع أي نوع بيانات، دون التضحية بالأداء (على عكس الدوال الافتراضية أو void*). يقوم المترجم بإنشاء نسخة منفصلة من الدالة أو الفئة لكل نوع محدد، مما يعطي أقصى سرعة في التنفيذ.

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



أساسيات بناء الجملة: كيفية تعريف واستخدام القالب

يتم تعريف القالب في C++ باستخدام الكلمة المفتاحية template والأقواس الزاوية <>، والتي تحتوي على معامل النوع (عادةً typename أو class).

دالة قالب

أبسط مثال هو دالة تُرجع القيمة القصوى من قيمتين:

template <typename T>T max(T a, T b) {    return (a > b) ? a : b;}

// الاستخدام:int main() { std::cout << max(3, 7) << std::endl; // 7 std::cout << max(3.14, 2.71) << std::endl; // 3.14 std::cout << max('a', 'z') << std::endl; // z return 0;}

لاحظ: المترجم يستنتج النوع T تلقائيًا بناءً على الوسائط المُمررة. إذا كنت بحاجة إلى تحديد النوع صراحةً، يمكنك كتابة max<double>(3.14, 2.71).



فئة قالب

تعمل القوالب أيضًا مع الفئات. مثال كلاسيكي هو حاوية "زوج" بسيطة:

template <typename T1, typename T2>class Pair {private:    T1 first;    T2 second;public:    Pair(T1 f, T2 s) : first(f), second(s) {}    T1 getFirst() const { return first; }    T2 getSecond() const { return second; }};

// الاستخدام:Pair<int, std::string> student(1, "Alice");std::cout << student.getFirst() << " " << student.getSecond();

هنا T1 و T2 هما معاملات القالب، والتي يمكن أن تكون أي نوع.



أمثلة عملية: من الحاويات البسيطة إلى الخوارزميات

دعنا نستعرض عدة سيناريوهات حقيقية حيث تكون الأنواع العامة لا غنى عنها.



فرز عام

سنكتب دالة قالب لفرز مصفوفة من أي نوع يدعم عامل المقارنة <:

template <typename T>void bubbleSort(T arr[], int n) {    for (int i = 0; i < n - 1; ++i)        for (int j = 0; j < n - i - 1; ++j)            if (arr[j] > arr[j + 1])                std::swap(arr[j], arr[j + 1]);}

// مثال:int intArr[] = {5, 2, 8, 1};bubbleSort(intArr, 4); // يعمل مع int

double dblArr[] = {3.14, 2.71, 1.41};bubbleSort(dblArr, 3); // يعمل مع double


مكدس (Stack) بنوع بيانات عشوائي

سننفذ مكدسًا بسيطًا يعتمد على القالب:

template <typename T>class Stack {private:    std::vector<T> elements;public:    void push(const T& value) { elements.push_back(value); }    void pop() { if (!elements.empty()) elements.pop_back(); }    T top() const { return elements.back(); }    bool empty() const { return elements.empty(); }};

// الاستخدام:Stack<int> intStack;intStack.push(10);intStack.push(20);std::cout << intStack.top(); // 20


خوارزمية "ابحث واستبدل"

دالة قالب تستبدل جميع تكرارات قيمة بأخرى في حاوية:

templa                

المدونات

توصيات الكتب