اختيار الكائنات القابلة للاستدعاء
Lambdas مقابل bind مقابل المؤشرات
اختيار الكائنات القابلة للاستدعاء درس مجاني في C++ Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C++ Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C++ Academy 4 دروس في المجموع.
صندوق أدوات الكيانات القابلة للاستدعاء
يوفر C++ عدة طرق لتمرير السلوك: مؤشرات الدوال ولامبدا وكائنات الدوال وstd::bind وstd::function. ولكل منها استخدامات مختلفة.
- المفاضلة المعتادة تكون بين السرعة والمرونة.
- وتهم سهولة القراءة أيضًا.
#include <iostream>
int twice(int x) { return x * 2; }
int main() {
int (*fp)(int) = twice;
auto lam = [](int x) { return x * 2; };
std::cout << fp(5) << ' ' << lam(5) << '\n';
return 0;
}متى تستخدم مؤشر دالة
استخدم مؤشر دالة عندما تحتاج إلى دالة ردّ اتصال صغيرة بلا حالة، وتريد التوافق مع C أو عدم إضافة أي عبء.
#include <iostream>
void logMsg(const char* m) { std::cout << "LOG: " << m << '\n'; }
int main() {
void (*handler)(const char*) = logMsg;
handler("started");
return 0;
}متى تستخدم لامبدا
لامبدا هي الخيار الافتراضي الحديث: فهي موجزة، ويمكنها التقاط الحالة، كما يضمّنها المترجم بكفاءة في القوالب والخوارزميات.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> v = {3, 1, 4, 1, 5};
std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
for (int x : v) std::cout << x << ' ';
std::cout << '\n';
return 0;
}التقاط الحالة في لامبدا
تلتقط لامبدا المتغيرات المحيطة، وهو أمر لا تستطيع مؤشرات الدوال فعله، مما يجعلها مثالية لدوال ردّ الاتصال التي تراعي السياق.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
int threshold = 3;
std::vector<int> v = {1, 2, 3, 4, 5};
int c = std::count_if(v.begin(), v.end(), [threshold](int x) { return x > threshold; });
std::cout << c << '\n';
return 0;
}متى تستخدم كائن دالة
يناسب كائن الدالة (وهو struct له operator()) عملية قابلة لإعادة الاستخدام وذات اسم، وقد يحمل إعدادات ويُستخدم في مواضع متعددة.
#include <iostream>
#include <vector>
#include <algorithm>
struct AboveThreshold {
int limit;
bool operator()(int x) const { return x > limit; }
};
int main() {
std::vector<int> v = {1, 5, 2, 8};
std::cout << std::count_if(v.begin(), v.end(), AboveThreshold{4}) << '\n';
return 0;
}لامبدا مقابل bind
يمكن لكليهما ملء الوسائط مسبقًا. وتكون صيغة لامبدا عادةً أوضح وأسهل على المترجم في تحسينها، لذا يُفضّل استخدامها بدلًا من std::bind.
#include <iostream>
int power(int base, int exp) {
int r = 1;
for (int i = 0; i < exp; ++i) r *= base;
return r;
}
int main() {
auto square = [](int x) { return power(x, 2); };
std::cout << square(6) << '\n';
return 0;
}متى تستخدم std::function
استخدم std::function عندما يتعين عليك تخزين كيان قابل للاستدعاء لا تعرف نوعه الملموس، مثلًا في عضو من أعضاء الصنف أو في حاوية.
#include <iostream>
#include <functional>
#include <vector>
int main() {
std::vector<std::function<int(int)>> pipeline;
pipeline.push_back([](int x) { return x + 1; });
pipeline.push_back([](int x) { return x * 3; });
int v = 2;
for (auto& f : pipeline) v = f(v);
std::cout << v << '\n';
return 0;
}القوالب تتجنب العبء الإضافي
إذا كانت الدالة تحتاج فقط إلى استقبال كيان قابل للاستدعاء، وليس تخزينه، فإن معامل القالب يحافظ على كامل السرعة من خلال تجنب محو النوع.
#include <iostream>
template <typename F>
int applyTwice(int x, F f) { return f(f(x)); }
int main() {
std::cout << applyTwice(3, [](int n) { return n + 10; }) << '\n';
return 0;
}ترتيب الأداء
بصورة تقريبية: يكون الكيان القابل للاستدعاء المعرّف باستخدام قالب أو لامبدا غير الملتقطة الأسرع، ويأتي مؤشر الدالة قريبًا منه، بينما يكون std::function الأبطأ بسبب الاستدعاء غير المباشر والتخصيص المحتمل.
#include <iostream>
#include <functional>
int main() {
auto fast = [](int x) { return x + 1; };
std::function<int(int)> flexible = fast;
std::cout << fast(1) << ' ' << flexible(1) << '\n';
return 0;
}دليل اتخاذ القرار
دليل سريع:
- هل تحتاج إلى تخزين أي كيان قابل للاستدعاء؟
std::function. - هل تحتاج فقط إلى استقبال كيان في دالة عامة؟ معامل قالب.
- هل تحتاج إلى سلوك مضمّن مع حالة؟ لامبدا.
- هل تحتاج إلى واجهة C أو كيان بلا حالة؟ مؤشر دالة.
#include <iostream>
#include <functional>
void runStored(const std::function<void()>& cb) { cb(); }
template <typename F>
void runGeneric(F f) { f(); }
int main() {
runStored([] { std::cout << "stored\n"; });
runGeneric([] { std::cout << "generic\n"; });
return 0;
}جمع كل ذلك
قد يستقبل نظام أحداث صغير معالجات بطريقة عامة، لكنه يخزّنها في std::function حتى يمكن استدعاؤها لاحقًا.
#include <iostream>
#include <functional>
#include <vector>
struct Dispatcher {
std::vector<std::function<void(int)>> handlers;
template <typename F> void on(F f) { handlers.emplace_back(f); }
void fire(int e) { for (auto& h : handlers) h(e); }
};
int main() {
Dispatcher d;
d.on([](int e) { std::cout << "got " << e << '\n'; });
d.fire(7);
return 0;
}اختبار سريع
اختبر مدى فهمك لاختيار الكيانات القابلة للاستدعاء.
مراجعة
لقد تعلمت كيفية اختيار كيان قابل للاستدعاء:
- مؤشر دالة لدوال ردّ الاتصال التي بلا حالة والمتوافقة مع C
- لامبدا كخيار افتراضي للسلوك المضمّن ذي الحالة
- كائن دالة للعمليات ذات الاسم والقابلة لإعادة الاستخدام
- معامل قالب عند استقبال كيان قابل للاستدعاء فقط، لتحقيق أعلى سرعة
std::functionعندما يتعين تخزين كيان لا يُعرف نوعه
وبذلك يكتمل مساق كائنات الدوال وstd::bind.
الأسئلة الشائعة
هل درس «اختيار الكائنات القابلة للاستدعاء» مجاني؟
نعم — نص درس «اختيار الكائنات القابلة للاستدعاء» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C++ Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C++ Academy 4 دروس في المجموع.
ماذا ستتعلم في «اختيار الكائنات القابلة للاستدعاء»؟
Lambdas مقابل bind مقابل المؤشرات تتمرن على C++ Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ C++ Academy؟
لا تُشترط خبرة سابقة. C++ Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «اختيار الكائنات القابلة للاستدعاء»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس C++ Academy هذا؟
نعم. كل درس في C++ Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- مؤشرات الدوال
- std::function
- std::bind
- اختيار الكائنات القابلة للاستدعاء