2009-02-17 8 views
2

Y at-il une méthode/modèle/bibliothèque pour faire quelque chose comme ça (en pseudo-code):C++ file d'attente méthode liée (? Gestionnaire de tâches/planificateur)

task_queue.push_back(ObjectType object1, method1); 
task_queue.push_back(OtherObjectType object2, method2); 

pour que je puisse faire le quelque chose comme:

for(int i=0; i<task_queue.size(); i++) { 
    task_queue[i].object -> method(); 
} 

afin qu'il appellerait:

obj1.method1(); 
obj2.method2(); 

Ou est-ce un rêve impossible?

Et s'il existe un moyen d'ajouter un certain nombre de paramètres à appeler, ce serait le meilleur.

Doug T. veuillez voir ceci Excellente réponse!

La version de Dave Van den Eynde fonctionne bien aussi.

Répondre

5

Oui, vous voudriez combiner boost::bind et boost::functions à son contenu très puissant.

Cette version est maintenant compilée, grâce à 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; 
}; 
+0

Impressionnant, mais que se passe-t-il si j'ai CClass1 et CClass2 et idéalement j'aimerais les stocker tous les deux? –

+0

Aussi je pense qu'il devrait y avoir _method = _ boost :: bind (AMethod, .... –

+0

Nit: bind copie ses arguments par défaut, de sorte que le commentaire "does instance.AMethod (...)" devrait se lire "Does * copy of * instance.AMethod() " Pour vraiment appeler l'instance, boost :: ref() (ou cref) devrait être utilisé pour envelopper l'instance passée à bind(). –

0

Peut-être que vous pourriez penser à une autre façon:

for(int i=0; i<task_queue.size(); i++) { 
    task_queue[i].method(task_queue[i].object); 
} 
+0

Cela signifie que la méthode task_queue() doit être surchargée pour chaque type d'objet, de sorte que la file d'attente de tâches doit connaître chaque type d'objet. Donc, pour ajouter un nouveau type d'objet, task_queue doit être changé, ce qui est mauvais. – KeithB

+0

Non, ici task_queue [i] est une instance de l'objet, pas de la task_queue. Donc, task_queue [i] .method() appelle la méthode qui est définie dans l'objet. Vous n'écrasez aucune méthode dans task_queue! –

2

Depuis C++ ne supporte pas les conteneurs hétérogènes, vos objets devront avoir une base commune (vous pouvez vous d'avoir un récipient pour les pointeurs vers cette classe de base).

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)); 

Vous essayez de mettre en œuvre le Hollywood principle autrement connu sous le nom de-inversion de contrôle (et aussi, la gestion des erreurs de poorman)?

Recherchez les modèleset Visitor - ils pourraient vous intéresser.

1

J'ai fouetté quelque chose.

#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; 
} 
+0

Wow! Cela fonctionne aussi, merci! Cependant, vos talents de modèle me brisent le cerveau :) Génial! –

+0

Eh bien, le gabarit n'est pas vraiment difficile. C'est la syntaxe du pointeur de la fonction membre qui m'a bogué quand je l'ai fait pour la première fois. –

Questions connexes