قائمة انتظار أسلوب C ++ (إدارة المهام / المجدول؟)
سؤال
هل هناك طريقة / نمط / مكتبة للقيام بشيء من هذا القبيل (في الكود الزائفي):
task_queue.push_back(ObjectType object1, method1);
task_queue.push_back(OtherObjectType object2, method2);
حتى أتمكن من القيام شيئا ما مثل:
for(int i=0; i<task_queue.size(); i++) {
task_queue[i].object -> method();
}
بحيث ستدعو:
obj1.method1();
obj2.method2();
أم أن حلم مستحيل؟
وإذا كانت هناك طريقة لإضافة عدد من المعلمات للاتصال - سيكون ذلك الأفضل.
دوغ ر. يرجى الاطلاع على هذا إجابة ممتازة!
ديف فان دن Eyndeالنسخة تعمل بشكل جيد أيضا.
المحلول
نعم كنت ترغب في الجمع بين دفعة :: BIND. و دفعة :: وظائف لها أشياء قوية جدا.
هذا الإصدار الآن يجمع الآن، وذلك بفضل slava!
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <vector>
class CClass1
{
public:
void AMethod(int i, float f) { std::cout << "CClass1::AMethod(" << i <<");\n"; }
};
class CClass2
{
public:
void AnotherMethod(int i) { std::cout << "CClass2::AnotherMethod(" << i <<");\n"; }
};
int main() {
boost::function< void (int) > method1, method2;
CClass1 class1instance;
CClass2 class2instance;
method1 = boost::bind(&CClass1::AMethod, class1instance, _1, 6.0) ;
method2 = boost::bind(&CClass2::AnotherMethod, class2instance, _1) ;
// does class1instance.AMethod(5, 6.0)
method1(5);
// does class2instance.AMethod(5)
method2(5);
// stored in a vector of functions...
std::vector< boost::function<void(int)> > functionVec;
functionVec.push_back(method1);
functionVec.push_back(method2);
for ( int i = 0; i < functionVec.size(); ++i)
{
functionVec[i]( 5);
};
return 0;
};
نصائح أخرى
نظرا لأن C ++ لا يدعم حاويات غير متجانسة، فسيتعين على الكائنات الخاصة بك أن يكون لديك قاعدة مشتركة (حتى تتمكن من الابتعاد مع وجود حاوية للمؤشرات إلى الفئة الأساسية هذه).
class shared_base {
public:
virtual void method() = 0; // force subclasses to do something about it
};
typedef std::list<shared_base*> obj_list;
class object : public shared_base {
public:
virtual void method() { methodx(); }
private:
int methodx();
};
// ...
list.insert(new object);
// ...
std::for_each(list.begin(), list.end(), std::mem_fun(&shared_base::method));
هل تحاول تنفيذ مبدأ هوليوود يعرف خلاف ذلك باسم انقلاب التحكم (وأيضا معالجة خطأ Pooman)؟
لقد جلدت شيئا ما.
#include <vector>
#include <algorithm>
#include <iostream>
template <typename ARG>
class TaskSystem
{
private:
class DelegateBase
{
public:
virtual ~DelegateBase() { }
virtual void Invoke(ARG arg) = 0;
};
template <typename T>
class Delegate : public DelegateBase
{
public:
typedef void (T::*Func)(ARG arg);
private:
Func m_func;
T* m_object;
public:
Delegate(T* object, Func func)
: m_object(object), m_func(func)
{ }
virtual void Invoke(ARG arg)
{
((*m_object).*(m_func))(arg);
}
};
typedef std::vector<DelegateBase*> Delegates;
Delegates m_delegates;
public:
~TaskSystem()
{
Clear();
}
void Clear()
{
Delegates::iterator item = m_delegates.begin();
for (; item != m_delegates.end(); ++item)
{
delete *item;
}
m_delegates.clear();
}
template <typename T>
void AddDelegate(T& object, typename Delegate<T>::Func func)
{
DelegateBase* delegate = new Delegate<T>(&object, func);
m_delegates.push_back(delegate);
}
void Invoke(ARG arg)
{
Delegates::iterator item = m_delegates.begin();
for (; item != m_delegates.end(); ++item)
{
(*item)->Invoke(arg);
}
}
};
class TaskObject1
{
public:
void CallOne(const wchar_t* value)
{
std::wcout << L"CallOne(): " << value << std::endl;
}
void CallTwo(const wchar_t* value)
{
std::wcout << L"CallTwo(): " << value << std::endl;
}
};
class TaskObject2
{
public:
void CallThree(const wchar_t* value)
{
std::wcout << L"CallThree(): " << value << std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
TaskSystem<const wchar_t*> tasks;
TaskObject1 obj1;
TaskObject2 obj2;
tasks.AddDelegate(obj1, &TaskObject1::CallOne);
tasks.AddDelegate(obj1, &TaskObject1::CallTwo);
tasks.AddDelegate(obj2, &TaskObject2::CallThree);
tasks.Invoke(L"Hello, World!\n");
return 0;
}
ربما يمكنك التفكير بطريقة أخرى:
for(int i=0; i<task_queue.size(); i++) {
task_queue[i].method(task_queue[i].object);
}