سؤال

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

#include <iostream>

class A
{
  double size;

  A( double (*f)() )
  {
    size = (*f)();
  };
};

double fun1()
{
  return 42.0;
}


int main()
{
  A a = A( &fun1() );

  std::cout << a.size << std::endl;
}

هذا بالطبع مثال أدنى. يعتمد الحجم المتغير على وظيفة معينة يجب تمريرها كوسيطة إلى الفصل. يتصور fun1 و fun2 كأنواع مختلفة من مولدات الأرقام العشوائية.

أعتقد أن طريقة Ideomatic في C ++ ستكون فئة تحمل المتغير ويتم تعديل الفئات الموروثة منه بواسطة تلك الوظيفة التي تختلف عن الكائنات (يرجى تصحيحي إذا كنت مخطئًا في هذا الافتراض). لكن سؤالي هو:

هل هناك أي إمكانية لتنفيذ نوع من مُنشئ الترتيب العالي؟ إذا كان الأمر كذلك ، فسيكون مثالًا رائعًا.

ملاحظة: إذا استخدمت بعض المصطلحات التقنية خاطئة ، سأكون سعيدًا بتصحيحه.

هل كانت مفيدة؟

المحلول

التغيير إلى:

A( double (*f)() )
{
    size = f();
};

و:

A a = A( fun1 );

عندما كنت تمر &fun1() كان ذلك يحاول استدعاء الوظيفة ثم أخذ عنوان النتيجة. ما تريده بالفعل هو مؤشر الوظيفة نفسه الذي يتم تخزينه fun1.

نصائح أخرى

هذا المثال لا معنى له ، لأنك لا تحفظ مؤشر الوظيفة للاستخدام لاحقًا. يمكنك إعادة كتابة هذا ببساطة إلى فقط

class A
{
    double size;

    A(double sz) {
        size = sz;
    };
};

double fun1()
{
    return 42.0;
}


int main()
{
    A a = A(fun1());
    std::cout << a.size << std::endl;
}

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

#include <iostream>

class A {
public:
    template<typename F>
    explicit A(F&& f) : size(f()) {

    };

    double size;
};

double fun1() {
    return 42.0;
}

int main() {
    A a(&fun1);
    std::cout << a.size << std::endl;
}

يبدو أنك بحاجة فقط إلى الوظيفة نفسها لتمريرها. لقد حصلت عليه تقريبا. هنا هو بناء الجملة الصحيح:

typedef double (*functype)();

void foo(functype f) {
    cout << f();
}

double bar() {
    return 2.39;
)

foo(bar); // don't call bar here, just pass it as address.

يمكنك أيضًا إعلان فو على النحو التالي:

void foo(double (*f)());

الوظائف ليست كائنات من الدرجة الأولى في C ++ ، وبالتالي فإن الطريقة الوحيدة لإنشاء إغلاق مع بعض المتغيرات (على سبيل المثال ، إذا كنت ترغب في حمل الوظيفة أو الاتصال بوظيفة عضو غير متكاملة) هي عوامل متعددة (كائنات ذات مشغل محمّل () ). هناك عدة طرق للحصول على هذا الكائن:

  1. حدده بنفسك ، قم بتخزين جميع المتغيرات اللازمة في الحقول وقم بتمريرها كوسيطة للوظيفة.
  2. استخدم وظائف Lambda C ++ 11 و STD :: وظيفة
  3. استخدم Boost :: Function and Boost :: Bind.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top