هل إعادة تفسير مؤشر وظيفة العضو "فكرة جيدة"؟
-
21-09-2019 - |
سؤال
لديّ موضوع عامل ، يحمل قائمة بـ "إجراءات الخيوط" ، ويعمل من خلالها كمتى.
template <class T> class ThreadAction
{
public:
typedef void (T::*action)();
ThreadAction(T* t, action f) :
func(f),obj(t) {}
void operator()() { (obj->*func)(); }
void (T::*func)();
T* obj;
};
يسمى عادة مثل هذا
myActionThread->addAction(
new ThreadAction<TheirClass>(this, &TheirClass::enable)
);
التي عملت بشكل جيد حتى
void TheirClass::enable()
تم تغييره إلى
bool TheirClass::enable()
للأسف لا يمكننا تغييره مرة أخرى لأن الأشياء الأخرى تحتاج إلى التنسيق الجديد ، (ولا يمكن أن تختلف عمليات التحميل الزائدة عن طريق نوع العودة وحدها).
لقد حاولت
myActionThread->addAction(
new ThreadAction<TheirClass>(this,
reinterpret_cast<void(TheirClass::*)>(&TheirClass::enable)
)
);
الذي يبدو أنه يعمل بشكل جيد ، لكنني لست متأكدًا من أن إعادة تفسير مؤشر الوظيفة مثل هذا هو سلوك "محدد" ، هل يمكن لأي شخص تقديم المشورة؟
المحلول
هذا بالتأكيد ليس السلوك المدعوم ، ويمكن أن يتسبب في تعطل البرنامج.
في الأساس ، تحتاج إلى عمل غلاف TheirClass::enable()
سيكون له نوع الإرجاع المناسب. سوف تكفي خط واحد بسيط:
public:
void enableWrapper() { enable(); };
ثم اتصل:
myActionThread->addAction(
new ThreadAction<TheirClass>(this, &TheirClass::enableWrapper)
);
إذا لم تتمكن من التعديل TheirClass
مباشرة ، ثم قم بإنشاء فئة فرعية بسيطة أو فئة مساعدة تنفذ الغلاف.
نصائح أخرى
يخطئ ، مما فهمته ، فأنت تلقي من طريقة تُرجع أ bool
إلى طريقة تعود void
?
قد يكون هذا خطيرًا ، اعتمادًا على اتفاقية الاتصال/العائدين المستخدمة. أنت ربما ننسى أن تبرز قيمة الإرجاع - أو تجاوز قيمة السجل مع قيمة الإرجاع.
ليست فكرة جيدة. فكر في إضافة معلمة قالب إضافية لنوع الإرجاع:
template <class T, typename RetType> class ThreadAction
{
public:
typedef RetType (T::*action)();
ThreadAction(T* t, action f) :
func(f),obj(t) {}
RetType operator()() { return (obj->*func)(); }
RetType (T::*func)();
T* obj;
};
هذا تطبيق إرجاع الفراغ.
أجد عمومًا أنه عندما يكون السؤال من النموذج "هل _______ فكرة جيدة؟" الجواب تقريبا تقريبا "لا!"
ربما يكون هذا صحيحًا بدون سياق.