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

المنشئات المفوضة

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

عندما يكون لديك عدة منشئات (constructors) تشترك في منطق تهيئة مشترك، يمكنك استخدام المنشئات المفوضة (delegating constructors) لتجنب تكرار الكود. يقوم المنشئ المفوض باستدعاء منشئ آخر من نفس الفئة في قائمة التهيئة الخاصة به.

class Player {
    std::string name;
    int health;
    int level;
public:
    // المنشئ الأساسي - يقوم بالعمل الفعلي
    Player(std::string n, int h, int lvl) 
        : name(n), health(h), level(lvl) {}
    
    // يفوض المنشئ الأساسي
    Player(std::string n) : Player(n, 100, 1) {}
    
    // المنشئ الافتراضي يفوض أيضاً
    Player() : Player("Unknown") {}
};

يحدث التفويض في قائمة التهيئة باستخدام اسم الفئة متبوعاً بالوسائط. عندما يتم استدعاء Player()، فإنه يفوض إلى Player(std::string)، والذي بدوره يفوض إلى المنشئ ذو المعاملات الثلاثة. تُنفذ السلسلة من المنشئ المستهدف وصولاً إلى المنشئ الأصلي.

هناك قاعدة واحدة مهمة: لا يمكن للمُنشئ المفوض (delegating constructor) أن يحتوي على أعضاء آخرين في قائمة التهيئة (initializer list) الخاصة به. يجب أن يكون التفويض هو العنصر الوحيد:

class Item {
    int id;
    int value;
public:
    Item(int i, int v) : id(i), value(v) {}
    
    // خطأ! لا يمكن الجمع بين التفويض وتهيئة الأعضاء
    // Item(int i) : Item(i, 0), id(i) {}
    
    // صحيح - التفويض فقط
    Item(int i) : Item(i, 0) {}
};

تساعد المنشئات المفوضة (Delegating constructors) في تركيز منطق التهيئة في مكان واحد، مما يجعل صيانة الكود أسهل ويقلل من احتمالية وقوع الأخطاء الناتجة عن تكرار الكود.

challenge icon

التحدي

سهل

لنقم ببناء نظام إعدادات اتصال يوضح كيف يمكن للمنشئات المفوضة (delegating constructors) القضاء على تكرار الكود من خلال ربط استدعاءات المنشئات معاً.

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

  • Connection.h: قم بتعريف فئة Connection التي تمثل اتصال شبكة بخيارات تكوين متنوعة. يجب أن تحتوي الفئة الخاصة بك على:
    • أعضاء خاصة (Private members): host (string)، و port (int)، و timeout (int بالثواني)، و secure (bool).
    • منشئ أساسي (primary constructor) يأخذ جميع المعاملات الأربعة ويقوم بتهيئة جميع الأعضاء باستخدام قائمة التهيئة (initializer list). يجب أن يطبع هذا المنشئ "Connection configured: <host>:<port>".
    • منشئ يأخذ host و port فقط ويفوض المنشئ الأساسي مع جعل timeout افتراضياً 30 و secure افتراضياً false.
    • منشئ يأخذ host فقط ويفوض المنشئ ذا المعاملين مع جعل port افتراضياً 80.
    • منشئ افتراضي (default constructor) يفوض المنشئ ذا المعامل الواحد مع جعل host افتراضياً "localhost".
    • دالة getInfo() تعيد سلسلة نصية (string) بالتنسيق التالي: "<host>:<port> (timeout: <timeout>s, secure: <yes/no>)".
  • main.cpp: قم بتوضيح سلسلة التفويض من خلال إنشاء اتصالات باستخدام منشئات مختلفة. اقرأ اسم المضيف (host name) ورقم المنفذ (port number) من المدخلات (كل منهما في سطر منفصل)، ثم:
    • أنشئ Connection باستخدام المنشئ الافتراضي.
    • أنشئ Connection باستخدام المضيف (host) من المدخلات فقط.
    • أنشئ Connection باستخدام كل من المضيف (host) والمنفذ (port) من المدخلات.
    • أنشئ Connection مع المضيف والمنفذ من المدخلات، و timeout بقيمة 60، و secure مضبوط على true.
    • اطبع getInfo() لكل اتصال، كل واحد في سطر منفصل.

تتدفق سلسلة التفويض كالتالي: المنشئ الافتراضي يستدعي المنشئ ذا المعامل الواحد، والذي بدوره يستدعي المنشئ ذا المعاملين، والذي يستدعي المنشئ الأساسي ذا المعاملات الأربعة. هذا يعني أن رسالة "Connection configured" ستُطبع مرة واحدة لكل كائن يتم إنشاؤه، ودائماً من المنشئ الأساسي.

بالنسبة لحالة الأمان في getInfo()، اطبع "yes" إذا كان secure صحيحاً (true)، وإلا اطبع "no".

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

ورقة مرجعية

يستدعي المنشئ المفوِّض (delegating constructor) منشئاً آخر من نفس الفئة في قائمة التهيئة الخاصة به لتجنب تكرار الكود:

class Player {
    std::string name;
    int health;
    int level;
public:
    // المنشئ الأساسي
    Player(std::string n, int h, int lvl) 
        : name(n), health(h), level(lvl) {}
    
    // يفوض إلى المنشئ الأساسي
    Player(std::string n) : Player(n, 100, 1) {}
    
    // المنشئ الافتراضي يفوض أيضاً
    Player() : Player("Unknown") {}
};

يحدث التفويض في قائمة التهيئة باستخدام اسم الفئة متبوعاً بالوسائط. يمكن للمنشئات أن تشكل سلسلة تفويض حيث يفوض أحدها الآخر.

قاعدة مهمة: لا يمكن للمنشئ المفوِّض أن يحتوي على أعضاء آخرين في قائمة التهيئة الخاصة به. يجب أن يكون التفويض هو العنصر الوحيد:

class Item {
    int id;
    int value;
public:
    Item(int i, int v) : id(i), value(v) {}
    
    // خطأ! لا يمكن الجمع بين التفويض وتهيئة الأعضاء
    // Item(int i) : Item(i, 0), id(i) {}
    
    // صحيح - تفويض فقط
    Item(int i) : Item(i, 0) {}
};

جرّب بنفسك

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

using namespace std;

int main() {
    // قراءة المدخلات
    string host;
    int port;
    cin >> host;
    cin >> port;

    // TODO: إنشاء Connection باستخدام الـ default constructor

    // TODO: إنشاء Connection باستخدام الـ host فقط من المدخلات

    // TODO: إنشاء Connection باستخدام كل من الـ host والـ port من المدخلات

    // TODO: إنشاء Connection مع الـ host والـ port المدخلين، و timeout=60، و secure=true

    // TODO: طباعة getInfo() لكل connection، واحدة في كل سطر

    return 0;
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming