0Pricing
C++ Academy · درس

std::function

خزّن أي كائن قابل للاستدعاء

std::function درس مجاني في C++ Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C++ Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C++ Academy 4 دروس في المجموع.

ما هو std::function؟

إن std::function غلاف لمحو النوع، ويمكنه احتواء أي كيان قابل للاستدعاء يطابق توقيعًا معينًا، مثل الدوال الحرة ولامبدا وكائنات الدوال والتعبيرات المربوطة.

  • يُصرَّح به باستخدام التوقيع المستهدف.
  • يوجد في <functional>.
#include <iostream>
#include <functional>

int add(int a, int b) { return a + b; }

int main() {
    std::function<int(int, int)> f = add;
    std::cout << f(2, 3) << '\n';
    return 0;
}

تخزين لامبدا

على خلاف مؤشر الدالة الخام، يخزّن std::function لامبدا بسهولة، حتى إن كانت تلتقط متغيرات.

#include <iostream>
#include <functional>

int main() {
    int offset = 10;
    std::function<int(int)> f = [offset](int x) { return x + offset; };
    std::cout << f(5) << '\n';
    return 0;
}

تخزين كائن دالة

إن كائن الدالة هو كائن له operator(). ويمكن لـ std::function تغليفه واستدعاء معامل التشغيل الخاص به عند استدعائه.

#include <iostream>
#include <functional>

struct Multiplier {
    int factor;
    int operator()(int x) const { return x * factor; }
};

int main() {
    std::function<int(int)> f = Multiplier{3};
    std::cout << f(4) << '\n';
    return 0;
}

إعادة تعيين الهدف

يمكن لمتغير واحد من نوع std::function أن يحتفظ بكيانات قابلة للاستدعاء مختلفة طوال فترة وجوده، وهو أمر مفيد لتبديل السلوك أثناء التشغيل.

#include <iostream>
#include <functional>

int main() {
    std::function<int(int)> f = [](int x) { return x + 1; };
    std::cout << f(10) << '\n';
    f = [](int x) { return x * x; };
    std::cout << f(10) << '\n';
    return 0;
}

std::function فارغ

لا يحتوي كائن std::function المُنشأ افتراضيًا على شيء. ويؤدي استدعاؤه إلى رمي std::bad_function_call، لذا اختبره أولًا.

#include <iostream>
#include <functional>

int main() {
    std::function<void()> f;
    if (f) {
        f();
    } else {
        std::cout << "empty\n";
    }
    return 0;
}

كوسيط

يمكن للدوال قبول وسيط من نوع std::function لاستقبال أي كيان قابل للاستدعاء يطابق التوقيع، مما يجعل واجهات برمجة التطبيقات مرنة.

#include <iostream>
#include <functional>

void repeat(int n, const std::function<void(int)>& action) {
    for (int i = 0; i < n; ++i) action(i);
}

int main() {
    repeat(3, [](int i) { std::cout << "step " << i << '\n'; });
    return 0;
}

تخزين دوال ردّ الاتصال

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

#include <iostream>
#include <functional>

struct Button {
    std::function<void()> onClick;
    void click() { if (onClick) onClick(); }
};

int main() {
    Button b;
    b.onClick = [] { std::cout << "clicked!\n"; };
    b.click();
    return 0;
}

متجه من الكيانات القابلة للاستدعاء

بما أنها تشترك في نوع واحد، يمكن أن تتواجد كيانات قابلة للاستدعاء مختلفة معًا في حاوية وأن تُستدعى بالتتابع.

#include <iostream>
#include <functional>
#include <vector>

int inc(int x) { return x + 1; }

int main() {
    std::vector<std::function<int(int)>> ops;
    ops.push_back(inc);
    ops.push_back([](int x) { return x * 2; });
    for (auto& op : ops) std::cout << op(10) << ' ';
    std::cout << '\n';
    return 0;
}

تكلفة محو النوع

قد يخصص std::function ذاكرة ويضيف استدعاءً غير مباشر، لذا فهو أبطأ قليلًا من الاستدعاء المباشر أو الكيان القابل للاستدعاء المعرّف باستخدام قالب. استخدمه عندما تحتاج إلى تخزين موحّد.

#include <iostream>
#include <functional>

int main() {
    std::function<int()> f = [] { return 42; };
    int total = 0;
    for (int i = 0; i < 5; ++i) total += f();
    std::cout << total << '\n';
    return 0;
}

إرجاع std::function

يمكن لدالة مصنع إنشاء كيان قابل للاستدعاء مُهيأ وإرجاعه، مما يتيح للمستدعين الحصول على سلوك مخصص.

#include <iostream>
#include <functional>

std::function<int(int)> adder(int n) {
    return [n](int x) { return x + n; };
}

int main() {
    auto add5 = adder(5);
    std::cout << add5(10) << '\n';
    return 0;
}

المقارنة مع مؤشرات الدوال

إن std::function أكثر مرونة من مؤشر الدالة لأنه يخزّن الحالة، لكن هذه المرونة تكلّف قليلًا من الأداء وقد تتطلب تخصيصًا للذاكرة.

#include <iostream>
#include <functional>

int main() {
    int base = 7;
    std::function<int(int)> stateful = [base](int x) { return x + base; };
    std::cout << "Stateful result: " << stateful(3) << '\n';
    return 0;
}

اختبار سريع

اختبر مدى فهمك لـ std::function.

مراجعة

لقد تعلمت أن std::function:

  • يغلّف أي كيان قابل للاستدعاء يطابق توقيعه، بما في ذلك لامبدا ذات الحالة وكائنات الدوال
  • يمكن إعادة تعيينه وتخزينه في حاويات وإرجاعه من دوال المصنع
  • يرمي bad_function_call عندما يكون فارغًا
  • يضيف عبئًا إضافيًا قليلًا بسبب محو النوع

بعد ذلك ستستخدم std::bind لملء وسائط الكيانات القابلة للاستدعاء مسبقًا.

الأسئلة الشائعة

هل درس «std::function» مجاني؟

نعم — نص درس «std::function» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C++ Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C++ Academy 4 دروس في المجموع.

ماذا ستتعلم في «std::function»؟

خزّن أي كائن قابل للاستدعاء تتمرن على C++ Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ C++ Academy؟

لا تُشترط خبرة سابقة. C++ Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «std::function»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس C++ Academy هذا؟

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

جميع الدروس في هذه الدورة

  1. مؤشرات الدوال
  2. std::function
  3. std::bind
  4. اختيار الكائنات القابلة للاستدعاء
← العودة إلى C++ Academy