التغيير إلى:
A( double (*f)() )
{
size = f();
};
و:
A a = A( fun1 );
عندما كنت تمر &fun1()
كان ذلك يحاول استدعاء الوظيفة ثم أخذ عنوان النتيجة. ما تريده بالفعل هو مؤشر الوظيفة نفسه الذي يتم تخزينه fun1
.
سؤال
حصلت على بعض الكائنات التي تعتمد المتغيرات على وظائف مختلفة. لوضعها بكلمات مختلفة: هناك أنواع متعددة من الوظائف التي تعتمد عليها المتغيرات في الكائن ، ولكن يجب أن يكون هناك كائنات متعددة مع نفس هذه الوظائف. لمزيد من التخليص ، حاولت إعطاء مثال (لا يعمل).
#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 ++ ، وبالتالي فإن الطريقة الوحيدة لإنشاء إغلاق مع بعض المتغيرات (على سبيل المثال ، إذا كنت ترغب في حمل الوظيفة أو الاتصال بوظيفة عضو غير متكاملة) هي عوامل متعددة (كائنات ذات مشغل محمّل () ). هناك عدة طرق للحصول على هذا الكائن: