Despacho múltiple en C ++

Estoy tratando de entender qué es el despacho múltiple. Leí muchos textos diferentes, pero aún no tengo idea de qué es el despacho múltiple y para qué sirve. Tal vez lo que me falta es una pieza de código que utiliza múltiples despachos. Por favor, ¿puedes escribir un pequeño fragmento de código en C ++ usando el envío múltiple para que pueda ver que no se puede comstackr / ejecutar correctamente porque C ++ solo tiene un solo despacho? Necesito ver la diferencia. Gracias.

El envío múltiple es la capacidad de elegir qué versión de una función llamar en función del tipo de tiempo de ejecución de los argumentos pasados ​​a la llamada a la función.

Aquí hay un ejemplo que no funcionará correctamente en C ++ (no probado):

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

El despacho múltiple ocurre cuando la función que se ejecuta depende del tipo de tiempo de ejecución de más de un objeto.

C ++ tiene despacho único porque cuando se usan funciones virtuales, la función real que se ejecuta depende solo del tipo de tiempo de ejecución del objeto a la izquierda de -> o. operador.

Estoy luchando por pensar en un caso de progtwigción real para despacho múltiple. Tal vez en un juego donde varios personajes luchan entre sí.

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

El ganador de una pelea puede depender de las características de ambos oponentes, por lo que es posible que desee que esta llamada se envíe a uno de los siguientes, según los tipos de tiempo de ejecución de ambos argumentos:

 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. 

Lo que hace la función depende de los tipos de ambos argumentos, no solo de uno. En C ++, puede que tenga que escribir esto como algunas funciones virtuales. Se seleccionaría una función virtual según un argumento (este puntero). Entonces, la función virtual puede necesitar contener un interruptor o algo para hacer algo particular al otro argumento.

Ver este artículo escrito por B. Stroustrup: Abrir Multi-Métodos para C ++

En el envío único, la función ejecutada depende únicamente del tipo de objeto. En el despacho doble, la función ejecutada depende del tipo de objeto y un parámetro.

En el siguiente ejemplo, la función Area() se invoca utilizando single dispatch, e Intersect() basa en double dispatch porque toma un parámetro Shape.

 class Circle; class Rectangle; class Shape { virtual double Area() = 0; // Single dispatch // ... virtual double Intersect(const Shape& s) = 0; // double dispatch, take a Shape argument virtual double Intersect(const Circle& s) = 0; virtual double Intersect(const Rectangle& s) = 0; }; struct Circle : public Shape { virtual double Area() { return /* pi*r*r */; } virtual double Intersect(const Shape& s); { return s.Intersect(*this) ; } virtual double Intersect(const Circle& s); { /*circle-circle*/ } virtual double Intersect(const Rectangle& s); { /*circle-rectangle*/ } }; 

El ejemplo se basa en este artículo .