البرمجة

كيفية تقاط this في لامبدا في C++

لماذا يتم طباعة “A::print()” مرتين عند تشغيل الكود؟ هذا السؤال يتعلق باللامبدا وطريقة التقاط القيم فيها. في الكود الخاص بك، قمت بتعريف دالة call_print في الفئة A التي تقوم بتعريف واستدعاء لامبدا print_func المخزنة في متغير محلي ثابت. هذه اللامبدا تقوم بطباعة الدالة print المحددة ضمن الكائن الحالي this، والذي يجب أن يكون مؤشرًا إلى كائن من الفئة A.

عندما تقوم بإنشاء كائنات A و B وتستدعي call_print على كلا الكائنين، يتم استدعاء اللامبدا مرتين، ويتم تقاطع قيمة this في كل مرة. السبب في ذلك هو أنه عند تعريف اللامبدا باستخدام [this]، فإنه يتم التقاط this بقيمته الحالية في نقطة تعريف اللامبدا، وليس في وقت استدعاء اللامبدا. وبما أن print_func هي متغير محلي ثابت، فإن اللامبدا تقترن دائمًا بـ this من الكائن الذي تم إنشاؤه أول مرة.

لحل هذه المشكلة والحصول على النتائج التي تتوقعها، يمكنك تغيير اللامبدا لتأخذ this كمعامل، بدلاً من التقاطه بشكل ضمني. يمكنك القيام بذلك عن طريق تعديل اللامبدا كما يلي:

cpp
static auto const print_func = [](A* self) { self->print(); };

ثم استخدامها في الطريقة call_print بالشكل التالي:

cpp
print_func(this);

بهذه الطريقة، يتم تمرير this كمعامل إلى اللامبدا، وبالتالي سيتم استخدام this الخاص بالكائن الحالي الذي يتم استدعاء call_print عليه.

المزيد من المعلومات

بالطبع! لامبدا (Lambda) في C++ هي وظيفة مجهولة الاسم (anonymous function) يمكن تعريفها في مكان واحد واستخدامها في مكان آخر. تُستخدم اللامبدا بشكل شائع لتمرير وظائف بين الدوال أو تخزينها في متغيرات. واحدة من ميزات اللامبدا في C++ هي قدرتها على التقاط (Capture) المتغيرات من النطاق الخارجي.

هناك ثلاثة أنواع من التقاط المتغيرات في اللامبدا في C++:

  1. التقاط بالقيمة ([=]): يتم نسخ قيم المتغيرات من النطاق الخارجي واستخدامها داخل اللامبدا. على سبيل المثال:

    cpp
    int x = 10; auto lambda = [=]() { return x; };
  2. التقاط بالمرجع ([&]): يتم التقاط المتغيرات بواسطة المرجع، مما يعني أن أي تغيير في المتغيرات داخل اللامبدا سيؤثر على النطاق الخارجي أيضًا. على سبيل المثال:

    cpp
    int y = 20; auto lambda = [&]() { return y; };
  3. التقاط محدد ([x] أو [&x]): يتم التقاط متغير محدد بالقيمة أو بالمرجع، على التوالي. على سبيل المثال:

    cpp
    int z = 30; auto lambda = [z]() { return z; }; // التقاط بالقيمة auto lambda2 = [&z]() { return z; }; // التقاط بالمرجع

أما بالنسبة لسؤالك الأصلي، فإن استخدام [this] في التقاط اللامبدا يؤدي إلى التقاط this بقيمته الحالية في نقطة تعريف اللامبدا، وليس في وقت استدعاء اللامبدا.

مقالات ذات صلة

زر الذهاب إلى الأعلى
إغلاق

أنت تستخدم إضافة Adblock

يرجى تعطيل مانع الإعلانات حيث أن موقعنا غير مزعج ولا بأس من عرض الأعلانات لك فهي تعتبر كمصدر دخل لنا و دعم مقدم منك لنا لنستمر في تقديم المحتوى المناسب و المفيد لك فلا تبخل بدعمنا عزيزي الزائر