Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

قوائم تهيئة المنشئ

جزء من قسم Object Oriented Programming في رحلة C++ على Coddy — الدرس 22 من 104.

لقد رأيت بناء جملة النقطتين الرأسيتين في الدروس السابقة مثل Player(std::string n, int h) : name(n), health(h) {}. يُسمى هذا قائمة تهيئة الأعضاء (member initializer list)، وهي الطريقة المفضلة لتهيئة الأعضاء في لغة C++.

تظهر قائمة التهيئة بعد قائمة معاملات المنشئ، وتبدأ بنقطتين رأسيتين. يتم تهيئة كل عضو مباشرة بقيمته، مع الفصل بينها بفاصلات:

class Rectangle {
    int width;
    int height;
    const int id;
    int& reference;
public:
    Rectangle(int w, int h, int i, int& r) 
        : width(w), height(h), id(i), reference(r) {
        // جسم المنشئ (يمكن أن يكون فارغاً)
    }
};

لماذا نستخدم قوائم التهيئة (initializer lists) بدلاً من التعيين (assignment) في جسم المنشئ (constructor body)؟ مع التعيين، يتم إنشاء الأعضاء (members) أولاً بشكل افتراضي، ثم يتم تعيين قيم جديدة لها. مع قوائم التهيئة، يتم إنشاء الأعضاء مباشرة بالقيم الصحيحة - وهذا أكثر كفاءة ومطلوب أحياناً.

أعضاء معينة يجب أن يتم تهيئتها باستخدام القائمة:

  • أعضاء const - لا يمكن تعيين قيم لها بعد الإنشاء
  • الأعضاء المرجعية (Reference members) - يجب ربطها عند التهيئة
  • أعضاء بدون منشئات افتراضية (default constructors)
class Player {
    const int maxHealth;    // يجب استخدام قائمة التهيئة
    std::string name;
public:
    // هذا يعمل
    Player(int max, std::string n) : maxHealth(max), name(n) {}
    
    // هذا لن يتم تجميعه (compile):
    // Player(int max) { maxHealth = max; }  // خطأ!
};

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

challenge icon

التحدي

سهل

لنقم ببناء نظام تهيئة لمحرك ألعاب يوضح متى ولماذا تكون قوائم تهيئة الأعضاء (member initializer lists) ضرورية. ستقوم بإنشاء فئة GameConfig تحتوي على أعضاء يجب تهيئتها باستخدام صيغة قائمة التهيئة.

ستقوم بإنشاء ملفين لتنظيم الكود الخاص بك:

  • GameConfig.h: قم بتعريف فئة GameConfig التي تخزن إعدادات اللعبة. يجب أن تحتوي الفئة على:
    • عضو const std::string gameName — عنوان اللعبة، والذي لا يمكن تغييره بعد الإنشاء.
    • عضو const int maxPlayers — الحد الأقصى لعدد اللاعبين، وهو ثابت عند الإنشاء.
    • عضو int& difficultyRef — مرجع (reference) لإعداد صعوبة خارجي.
    • عضوين int screenWidth و int screenHeight — أعضاء عاديين لإعدادات العرض.
    • منشئ (constructor) يأخذ جميع المعلمات اللازمة ويقوم بتهيئة كل عضو باستخدام قائمة التهيئة (initializer list). يجب أن تتبع قائمة التهيئة ترتيب التصريح عن الأعضاء في الفئة.
    • دالة display() تقوم بطباعة التهيئة بهذا التنسيق:
      Game: <gameName>
      Max Players: <maxPlayers>
      Difficulty: <difficultyRef value>
      Resolution: <screenWidth>x<screenHeight>
  • main.cpp: قراءة قيم التهيئة من المدخلات وإنشاء كائن GameConfig. ستحتاج إلى:
    • قراءة اسم اللعبة (string)، والحد الأقصى للاعبين (int)، والصعوبة (int)، والعرض (int)، والارتفاع (int) من المدخلات — كل منها في سطر منفصل.
    • إنشاء متغير int محلي للصعوبة سيشير إليه كائن التهيئة.
    • إنشاء كائن GameConfig باستخدام منشئ قائمة التهيئة.
    • استدعاء display() لإظهار التهيئة الأولية.
    • تعديل متغير الصعوبة مباشرة (اضربه في 2).
    • طباعة "After difficulty change:".
    • استدعاء display() مرة أخرى لإظهار أن المرجع يعكس القيمة المحدثة.

يسلط هذا التحدي الضوء على سبب أهمية قوائم التهيئة: أعضاء const والعضو المرجعي (reference member) لا يمكن تعيين قيم لهم داخل جسم المنشئ — يجب تهيئتهم في القائمة. كما يوضح العضو المرجعي كيف تنعكس التغييرات في المتغير الأصلي من خلال كائن التهيئة.

قم بتضمين ملف الرأس الخاص بك في main.cpp باستخدام #include "GameConfig.h".

ورقة مرجعية

تعد قائمة تهيئة الأعضاء (member initializer list) هي الطريقة المفضلة لتهيئة أعضاء الفئة في لغة C++. تظهر بعد قائمة معاملات المنشئ (constructor)، وتبدأ بنقطتين رأسيتين، حيث يتم تهيئة كل عضو مباشرة:

class Rectangle {
    int width;
    int height;
public:
    Rectangle(int w, int h) : width(w), height(h) {
        // جسم المنشئ
    }
};

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

مطلوبة لأعضاء معينين:

  • أعضاء const - لا يمكن تعيين قيم لها بعد الإنشاء
  • أعضاء المراجع (Reference members) - يجب ربطها عند التهيئة
  • الأعضاء التي لا تملك منشئات افتراضية
class Player {
    const int maxHealth;
    int& reference;
public:
    // صحيح - يستخدم قائمة التهيئة
    Player(int max, int& r) : maxHealth(max), reference(r) {}
    
    // خطأ - لا يمكن تعيين قيمة لثابت أو مرجع داخل الجسم
    // Player(int max) { maxHealth = max; }
};

هام: يتم تهيئة الأعضاء حسب ترتيب التصريح عنها في الفئة، وليس حسب ترتيبها في قائمة التهيئة. احرص دائماً على كتابة قائمة التهيئة بنفس ترتيب التصريح.

جرّب بنفسك

#include <iostream>
#include <string>
#include "GameConfig.h"

using namespace std;

int main() {
    // قراءة قيم المدخلات
    string gameName;
    getline(cin, gameName);
    
    int maxPlayers;
    cin >> maxPlayers;
    
    int difficulty;
    cin >> difficulty;
    
    int width;
    cin >> width;
    
    int height;
    cin >> height;
    
    // TODO: إنشاء كائن GameConfig باستخدام منشئ قائمة التهيئة (initializer list constructor)
    // يجب أن يستقبل المنشئ: gameName، maxPlayers، difficulty (عن طريق المرجع)، width، height
    
    // TODO: استدعاء display() لعرض الإعدادات الأولية
    
    // TODO: تعديل متغير difficulty مباشرة (بضربه في 2)
    
    // TODO: طباعة "After difficulty change:"
    
    // TODO: استدعاء display() مرة أخرى لعرض الإعدادات المحدثة
    
    return 0;
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming