2017-10-07 7 views
0

Nous concevons un nouveau système dans lequel nous avons créé des interfaces pour la plupart de nos classes afin de pouvoir créer des mocks (google mocks) pour les tests unitaires. En conséquence, toutes les fonctions sont virtuelles mais le problème est que je cours souvent dans le problème de fonction virtuelle de modèle dû à ceci. J'ai vu quelques exemples sur la façon de faire multi dispatch, mais ils semblent tous utiliser une certaine variation de modèles, cela ne semble pas simple. Cela signifie-t-il que toute ma base de code se retrouvera désormais avec des modèles rendant la lecture/l'utilisation et le débogage difficiles?Problème de fonctionnement du modèle virtuel C++ en raison de la programmation basée sur l'interface

Ou ne suis-je pas en train de concevoir de bonnes interfaces. Voici un exemple simple où j'écris une interface pour une file d'attente de messages.

Class IMessageQueue { 

    Public: 

    Virtual int send(const T & value); // I can't do this but this is exactly what I want to do, as send should be able to send any type 

}; 

Class MessageQueue : public IMessageQueue { 
     Public: 

     Virtual int send(const T & value) { ... } 
}; 

Class MockMQ : public IMessageQueue { 
     Public: 
     Virtual int send(const T & value) { 
       // mock implementation 
      } 
}; 

Comment contourner ce problème? Ceci est juste un exemple mais je rencontre beaucoup de ces types de problèmes en raison de la programmation basée sur l'interface.

+0

Vous pouvez probablement vous déplacer les en les rendant non virtuelles et ayant une fonction d'assistance qui détermine le type par dynamic_cast et appelle ensuite la fonction membre modélisée de ce type spécifique. Je ne sais pas à quel point cela finirait dans votre cas particulier, et je n'ai jamais essayé cela. – Sopel

Répondre

0

Cela dépend si vous avez besoin de votre IMessageQueue pour envoyer un type inconnu spécifique ou n'importe quel type. Ce n'est pas la même chose.

Un type inconnu spécifique peut être géré par

template<typename T> 
class IMessageQueue { 
public: 
    virtual int send(const T& value); 
} 

Alors que vous pouvez avoir votre IMessageQueue<MyMessage> et IMessageQueue<OtherMessage>.

Si, au contraire, vous devez être en mesure d'envoyer tout type avec le même type de file d'attente de messages, votre option est de déclarer une interface spécifique commune à tous les messages comme dans

class Message 
{ 
protected: 
    Message() : { .. } 
}; 

class MyMessage : public Message 
{ 
.. 
}; 

class MessageQueue 
{ 
public: 
    void send(const Message& message); 
}; 
+0

Merci Jack. Si IMesageQueue est une classe template alors envoyer ne peut plus être virtuel, non? J'aime mieux la deuxième solution, mais cela signifie-t-il que j'ai besoin de créer une nouvelle sous-classe de type de message chaque fois que j'ai besoin d'envoyer un nouveau type de données? Je veux créer une bibliothèque et l'exposer de sorte que je n'aurai pas la flexibilité de changer de bibliothèque souvent. Nous pouvons probablement faire un message comme modèle mais je pense que nous reviendrons au même problème encore une fois que la méthode send() d'IMessage prendra le Mesage et cela ne nous permettra pas non plus de faire envoyer en tant que virtuel. – maverick112