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

تحميل العوامل [] و ()

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

يسمح عامل الفهرسة ([]) لفئتك بالتصرف مثل المصفوفة، مما يوفر وصولاً مفهرساً للعناصر. كما يحول عامل استدعاء الدالة (()) الكائنات إلى كيانات قابلة للاستدعاء، تُعرف باسم functors.

إليك غلاف مصفوفة بسيط مع عامل الفهرسة (subscript operator):

class IntArray {
    int* data;
    size_t size;
    
public:
    IntArray(size_t s) : size(s), data(new int[s]()) {}
    ~IntArray() { delete[] data; }
    
    int& operator[](size_t index) {
        return data[index];
    }
    
    const int& operator[](size_t index) const {
        return data[index];
    }
};

لاحظ أننا نوفر نسختين: إحداهما تعيد مرجعاً غير ثابت (non-const reference) (مما يسمح بالتعديل)، والنسخة الثابتة (const) تعمل مع الكائنات الثابتة (const objects). هذا يتيح لك كتابة arr[0] = 5; للقراءة والكتابة.

يُنشئ عامل استدعاء الدالة (function call operator) كائنات يمكن "استدعاؤها" مثل الدوال:

class Multiplier {
    int factor;
    
public:
    Multiplier(int f) : factor(f) {}
    
    int operator()(int value) const {
        return value * factor;
    }
};

Multiplier triple(3);
int result = triple(10);    // يعيد 30

تعتبر الفانكتورز (Functors) قوية لأنها تستطيع الحفاظ على الحالة بين الاستدعاءات، على عكس الدوال العادية. وهي تُستخدم بشكل شائع مع خوارزميات STL حيث تحتاج إلى سلوك قابل للتخصيص يتذكر قيم الإعدادات.

challenge icon

التحدي

سهل

لنقم ببناء فئة ScoreTracker تجمع بين عاملي الـ subscript (الوصول عبر الفهرس) و function call (استدعاء الدالة). ستقوم هذه الفئة بتخزين درجات اللاعبين وتسمح لك بالوصول إليها عن طريق الفهرس باستخدام []، بينما تعمل أيضاً كـ functor يطبق مضاعف مكافأة (bonus multiplier) على أي درجة تمررها إليها.

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

  • ScoreTracker.h: قم بتعريف فئة ScoreTracker التي تدير مصفوفة من درجات اللاعبين ويمكنها تطبيق المكافآت. يجب أن تحتوي الفئة الخاصة بك على:
    • مصفوفة int* مخصصة ديناميكياً لتخزين الدرجات
    • عضو من نوع size_t لعدد الدرجات
    • عضو من نوع double لمضاعف المكافأة
    • منشئ (constructor) يأخذ الحجم ومضاعف المكافأة، ويقوم بتهيئة جميع الدرجات إلى 0
    • مدمر (destructor) يقوم بتنظيف الذاكرة الديناميكية بشكل صحيح
    • عامل الـ subscript [] (بإصداري const و non-const) للوصول إلى الدرجات عن طريق الفهرس
    • عامل استدعاء الدالة () الذي يأخذ درجة من نوع int ويعيد الدرجة مضروبة في مضاعف المكافأة (كـ int)
    • طريقة getSize() تعيد عدد الدرجات

    يعيد عامل الـ subscript غير الثابت (non-const) مرجعاً بحيث يمكنك كتابة tracker[0] = 100;. بينما يسمح إصدار const بالوصول للقراءة فقط للكائنات الثابتة. يجب تمييز عامل استدعاء الدالة بـ const لأنه لا يعدل حالة الكائن.

  • main.cpp: اقرأ المدخلات التالية (كل منها في سطر منفصل):
    1. عدد اللاعبين (الحجم)
    2. مضاعف المكافأة (كـ double)
    3. درجات كل لاعب (واحدة في كل سطر، بعدد الحجم)
    4. درجة اختبار لتطبيق المكافأة عليها

    قم بإنشاء ScoreTracker، واستخدم عامل الـ subscript لتخزين درجة كل لاعب، ثم اعرض جميع الدرجات. أخيراً، استخدم عامل استدعاء الدالة لحساب الدرجة بعد تطبيق المكافأة.

    تنسيق المخرجات:

    Player 0: <score>
    Player 1: <score>
    ...
    Bonus applied to <test_score>: <result>

على سبيل المثال، مع 3 لاعبين، ومضاعف 1.5، ودرجات 100، 200، 150، ودرجة اختبار 80:

Player 0: 100
Player 1: 200
Player 2: 150
Bonus applied to 80: 120

استخدم std::stoi() و std::stod() لتحويل المدخلات. لا تنسَ حواجز التضمين (header guards) في ملف الترويسة الخاص بك.

ورقة مرجعية

يسمح عامل الفهرسة [] بالوصول إلى الكائنات مثل المصفوفات. يجعل عامل استدعاء الدالة () الكائنات قابلة للاستدعاء مثل الدوال (الكائنات الدالية).

عامل الفهرسة

توفير نسختين ثابتة (const) وغير ثابتة (non-const) للوصول للقراءة والكتابة:

class IntArray {
    int* data;
    size_t size;
    
public:
    IntArray(size_t s) : size(s), data(new int[s]()) {}
    ~IntArray() { delete[] data; }
    
    // نسخة غير ثابتة: تسمح بالتعديل
    int& operator[](size_t index) {
        return data[index];
    }
    
    // نسخة ثابتة: وصول للقراءة فقط
    const int& operator[](size_t index) const {
        return data[index];
    }
};

عامل استدعاء الدالة

ينشئ كائنات دالية (functors) يمكنها الحفاظ على الحالة بين الاستدعاءات:

class Multiplier {
    int factor;
    
public:
    Multiplier(int f) : factor(f) {}
    
    int operator()(int value) const {
        return value * factor;
    }
};

Multiplier triple(3);
int result = triple(10);    // يعيد 30

الكائنات الدالية مفيدة مع خوارزميات STL حيث تكون هناك حاجة لسلوك قابل للتخصيص مع إعدادات مخزنة.

جرّب بنفسك

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

using namespace std;

// TODO: تنفيذ منشئ ScoreTracker
ScoreTracker::ScoreTracker(size_t size, double multiplier) {
    // TODO: تهيئة الأعضاء وتخصيص مصفوفة ديناميكية
    // تهيئة جميع الدرجات إلى 0
}

// TODO: تنفيذ مدمر ScoreTracker
ScoreTracker::~ScoreTracker() {
    // TODO: تنظيف الذاكرة الديناميكية
}

// TODO: تنفيذ عامل الفهرسة (subscript operator) غير الثابت (non-const)

// TODO: تنفيذ عامل الفهرسة (subscript operator) الثابت (const)

// TODO: تنفيذ عامل استدعاء الدالة (function call operator)

// TODO: تنفيذ تابع getSize
size_t ScoreTracker::getSize() const {
    // TODO: إرجاع عدد الدرجات
}

int main() {
    string line;
    
    // قراءة عدد اللاعبين
    getline(cin, line);
    size_t numPlayers = stoi(line);
    
    // قراءة مُعامل المكافأة (bonus multiplier)
    getline(cin, line);
    double multiplier = stod(line);
    
    // TODO: إنشاء ScoreTracker باستخدام numPlayers و multiplier
    
    // TODO: قراءة الدرجات لكل لاعب وتخزينها باستخدام عامل الفهرسة (subscript operator)
    
    // TODO: قراءة درجة الاختبار
    
    // TODO: عرض جميع درجات اللاعبين بالتنسيق: "Player X: <score>"
    
    // TODO: عرض نتيجة تطبيق المكافأة بالتنسيق: "Bonus applied to <test_score>: <result>"
    
    return 0;
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming