2010-05-04 2 views
1
class Message {}; 
class BuildSandCastle : public Message {}; 
class DigHole : public Message {}; 

Étant donné un objet Message* arbitraire, comment puis-je appeler une fonction du même nom doMessage() sans avoir recours à changer la logique ou de faire une classe MessageHandler qui a un « faire 'fonction pour chaque nom de message?Comment appeler une fonction particulière en fonction d'un type d'objet particulier

EDIT: par exemple:

class Sandbox 
{ 
public: 
    void play(Message* m) 
    { 
    // call doBuildSandCastle 
    // or doDigHole based on m's type 
    } 
    void doBuildSandCastle(); 
    void doDigHole(); 
}; 

Désolé, je n'étais pas clair avant.

EDIT:

quelqu'un peut-il supprimer simplement cette épave du train d'une question? Je ne veux vraiment pas toutes ces leçons de lycée dans le polymorphisme.

+0

Maintenant que votre question est plus claire ... Vous pouvez soit obtenir votre objet de message pour appeler la bonne fonction: 'void play (Message * m) {m-> play (this); } ' ou vous pouvez avoir une carte de pointeurs de fonction dans' Sandbox' et exécuter la fonction appropriée basée sur le nom du message (ou ID_type), par ex. 'handler_map [m.name()]();' –

Répondre

0

Je cherchais quelque chose comme this

class MessageHandlerBase 
{}; 

template<typename MessageType> 
class MessageHandler: 
    public virtual MessageHandlerBase 
{ 
    virtual void process(MessageType*)=0; 
}; 

class Message 
{ 
protected: 
    template<typename MessageType> 
    void dynamicDispatch(MessageHandlerBase* handler,MessageType* self) 
    { 
     dynamic_cast<MessageHandler<MessageType>&>(*handler).process(self); 
    } 
}; 
class Message1: 
    public MessageBase 
{ 
    void dispatch(MessageHandlerBase* handler) 
    { 
     dynamicDispatch(handler,this); 
    } 
}; 

Sauf sans avoir à utiliser dynamic_cast , ou en passant le message lui-même (un la le code dans la question d'origine.)

0

Utiliser des fonctions virtuelles.

class Message { 
    virtual void doSomething(...) = 0; 
}; 

class ReportMessage : public Message { 
    virtual void doSomething(...) { 
    // (...) - specific for repors 
    } 
}; 

class BankReportMessage : public ReportMessage { 
    virtual void doSomething(...) { 
    // (...) -||- for banks 
    } 
}; 

Maintenant, quelque part dans votre code:

Message* my_message = new BankReportMessage(...); 
my_message->doSomething(...); // Would call appropriate function 
0

Sons comme les devoirs, vous devriez probablement à virtual fonctions (wikipedia). Le message devrait probablement avoir doMessage virtuel pur, qui est surchargé dans les sous-classes.

8

EDIT: Maintenant que la question a été clarifiée, voici la nouvelle réponse:

Vous pouvez obtenir votre objet de message pour appeler la fonction droite:

void play(Message* m) { m->play(this); } 

ou vous pourriez avoir une carte des pointeurs de fonction dans Sandbox et exécuter la fonction appropriée basée sur le nom du message (ou typeid), par exemple J'utiliserais Boost :: function pour stocker des pointeurs de fonction dans une carte.


RÉPONSE VIEUX: Je pense que ce que vous avez besoin est des fonctions virtuelles:

class Message 
{ 
    virtual void doMessage { std::cout << "message" << std::endl; } 
}; 
class BuildSandCastle : public Message 
{ 
    virtual void doMessage { std::cout << "build sand castle" << std::endl; } 
}; 
class BuildSandCastle : public Message 
{ 
    virtual void doMessage { std::cout << "dig hole" << std::endl; } 
}; 

Lorsque vous appelez doMessage comme ceci:

Message* msg = new BuildSandCastle(); 
msg->doMessage(); 

sortie sera "construire le château de sable".

2

Il semble que vous essayez simplement d'ajouter une fonction polymorphe à certaines classes. En supposant que les paramètres et les valeurs de retour sont identiques sur les sous-classes, vous pouvez ajouter une fonction virtuelle pure à la classe de base.

par exemple: (note: Je ne compile pas cela, donc des excuses s'il y a des fautes de frappe)

class Message 
{ 
    public: 
    virtual void doMessage() = 0; 
}; 

class BuildSandCaste : public Message 
{ 
    public: 
    void doMessage() { /* build a sand castle */ } 
}; 

class DigHole : public Message 
{ 
    public: 
    void doMessage() { /* dig hole */ } 
}; 
+2

Il est généralement recommandé de mettre 'virtual' avant chaque déclaration de fonction (pas seulement dans la classe de base), afin que quelqu'un qui inspecte votre interface puisse facilement distinguer' virtual 'et' non-virtual' méthodes. –

Questions connexes