2009-11-17 10 views
29

J'essaie de comprendre ce qu'est la répartition multiple. J'ai lu beaucoup de textes différents mais je n'ai toujours aucune idée de ce qu'est la répartition multiple et de ce à quoi elle sert. Peut-être que la chose qui me manque est un morceau de code utilisant plusieurs dépêches. S'il vous plaît, pouvez-vous écrire un petit morceau de code en C++ en utilisant plusieurs dispatch afin que je puisse voir qu'il ne peut pas être compilé/exécuté correctement parce que C++ n'a qu'une seule distribution? J'ai besoin de voir la différence. Merci.Envoi multiple en C++

+2

C++ ne supporte pas directement, mais je suis sûr que vous pouvez en quelque sorte imiter cela. Je n'ai jamais utilisé MD ou même vu un joli design dans d'autres langues qui m'a donné envie d'avoir MD en C++. Les fanboys de Dylan l'énumèrent comme l'une des caractéristiques du langage de Dylan. Mais autant que je puisse dire, ça sent mauvais comme un design parce que le nombre de fonctions que vous pourriez avoir à écrire augmente de façon exponentielle. Je ne voudrais pas écrire autant de fonctions. – sellibitze

+4

Vous avez utilisé MD à chaque fois que vous avez utilisé le modèle 'Visitor'. –

+1

Un exemple simple en utilisant C++ 11: http://ideone.com/lTsc7M – Jarod42

Répondre

54

La répartition multiple permet de choisir la version d'une fonction à appeler en fonction du type d'exécution des arguments transmis à l'appel de fonction.

Voici un exemple qui ne fonctionnera pas droit en C++ (non testé):

class A { }; 
class B : public A { }; 
class C : public A { } 


class Foo 
{ 
    virtual void MyFn(A* arg1, A* arg2) { printf("A,A\n"); } 
    virtual void MyFn(B* arg1, B* arg2) { printf("B,B\n"); } 
    virtual void MyFn(C* arg1, B* arg2) { printf("C,B\n"); } 
    virtual void MyFn(B* arg1, C* arg2) { printf("B,C\n"); } 
    virtual void MyFn(C* arg1, C* arg2) { printf("C,C\n"); } 
}; 

void CallMyFn(A* arg1, A* arg2) 
{ 
    // ideally, with multi-dispatch, at this point the correct MyFn() 
    // would be called, based on the RUNTIME type of arg1 and arg2 
    pFoo->MyFn(arg1, arg2); 
} 

... 

A* arg1 = new B(); 
A* arg2 = new C(); 
// Using multi-dispatch this would print "B,C"... but because C++ only 
// uses single-dispatch it will print out "A,A" 
CallMyFn(arg1, arg2); 
+2

+1 pour le code qui indique clairement le problème – neuro

+1

Merci, cette réponse est à peu près ce que j'avais besoin de voir.Maintenant, je dois juste savoir, pourquoi diable quelqu'un a besoin d'une telle chose .. Quoi qu'il en soit, je vous remercie pour le bon exemple. – Martin

+3

une application est la physique, un cube entrant en collision avec un autre cube est une intersection, un cube entrant en collision avec un plan est une intersection différente. Par conséquent, vous vous retrouvez avec pas mal de méthodes différentes de détection de collision, et la répartition est très utile pour cela. heres un fil sur double expédition, http://www.gamedev.net/topic/453624-double-dispatch-in-c/ – QuantumKarl

18

envoi multiple est lorsque la fonction qui est exécuté dépend du type de temps d'exécution de plus d'un objet.

C++ a une répartition unique, car lorsque vous utilisez des fonctions virtuelles, la fonction réelle qui s'exécute dépend uniquement du type d'exécution de l'objet à gauche de -> ou. opérateur.

J'ai du mal à penser à un vrai cas de programmation pour les envois multiples. Peut-être dans un jeu où différents personnages se battent entre eux.

void Fight(Opponent& opponent1, Opponent& opponent2); 

Le gagnant d'un combat peut dépendre des caractéristiques des deux adversaires, vous voudrez peut-être cet appel à expédier à l'un des éléments suivants, en fonction des types temps d'exécution des deux arguments:

void Fight(Elephant& elephant, Mouse& mouse) 
{ 
    mouse.Scare(elephant); 
} 

void Fight(Ninja& ninja, Mouse& mouse) 
{ 
    ninja.KarateChop(mouse); 
} 

void Fight(Cat& cat, Mouse& mouse) 
{ 
    cat.Catch(mouse); 
} 

void Fight(Ninja& ninja, Elephant& elephant) 
{ 
    elephant.Trample(ninja); 
} 

// Etc. 

La fonction dépend du type des deux arguments, pas d'un seul. En C++, vous devrez peut-être écrire ceci comme des fonctions virtuelles. Une fonction virtuelle serait sélectionnée en fonction d'un argument (le pointeur this). Ensuite, la fonction virtuelle peut avoir besoin de contenir un commutateur ou quelque chose pour faire quelque chose de particulier à l'autre argument.

+2

+1 pour les noms ;-) – neuro

+4

Il me manque des pirates. Mais ok, merci par exemple. – Martin

+3

Un exemple pratique, qui arrive souvent, consiste à traiter différentes sous-classes différemment d'un tableau de pointeurs de classe de base. – kizzx2

3

Dans envoi unique La fonction exécutée dépend uniquement du type d'objet. Dans double répartition la fonction exécutée dépend du type d'objet et d'un paramètre .

Dans l'exemple suivant, la fonction Area() est appelée à l'aide envoi simple et Intersect() se fie à l'expédition à double car il faut un paramètre de forme. L'exemple est basé sur cette article.

+0

+1 lien intéressant – neuro

+0

Beaucoup d'espaces là-bas. – strager

+1

@strager 2 espaces supplémentaires :) Ce serait bien si Stack Overflow pouvait le mettre en forme sur le nombre d'espaces que le spectateur préfère. – pilkch

11

Voir cet article écrit par B. Stroustrup: Open Multi-Methods for C++

+1

bien que j'ai donné un +1, vous étiez censé mettre un résumé pour cet article ... Aussi l'article ne couvre que la méthode de remplacement, pas tous les cas de répartition multiples. –