¿Qué es el despacho? ¿Implica una resolución dinámica?

8

AFAIK, el término despacho significa solo una resolución de método y una llamada. No importa si es estático o dinámico. Vi que muchas personas están usando un término como despacho estático y despacho dinámico .

Lo que me confunde es que también hay algunas descripciones misteriosas. Estaba tratando de entender qué es el envío múltiple , y parece que solo selecciono un subprograma por tipos de parámetros . Si lo entendí correctamente, puede haber un despacho múltiple estático y un despacho múltiple dinámico , y podemos decir que C ++ está proporcionando despacho múltiple a través de funciones gratuitas.

Pero, el artículo de Wikipedia sobre despacho múltiple dice que C ++ no tiene despacho múltiple porque no tiene una resolución dinámica de función por múltiples parámetros. Y realmente no obtengo una diferencia conceptual entre el ejemplo de Common Lisp y la función sobrecargada de C ++. Porque no puedo encontrar ninguna diferencia conceptual a menos que el término despacho múltiple implique despacho dinámico . Y me di cuenta de que estoy confundiendo lo que realmente es el despacho

También verifiqué la entrada de control de calidad Despacho múltiple frente a sobrecarga de funciones , y parece que la respuesta es que el término despacho es básicamente dinámico . Eso también me confunde.

¿Cuál es el significado correcto del término despacho ? ¿Implica una resolución dinámica ? ¿Este término está bien definido o es simplemente convencional? ¿Qué me estoy perdiendo?

Eonil
fuente
1
"El artículo de Wikipedia sobre despacho múltiple dice que C ++ no tiene despacho múltiple", ¿a qué artículo se refiere? C ++ tiene despacho múltiple. Y sí, el envío múltiple implica dinámico (ver en.wikipedia.org/wiki/Multiple_dispatch )
miraculixx
@miraculixx Ese es el artículo. Y el artículo de Wikipedia no menciona el atributo estático / dinámico, así que estaba completamente confundido.
Eonil
1
@miraculixx - C ++ no tiene despacho múltiple. Debe simularlo con algún patrón de diseño, como el Patrón de visitante.
David Hammen
@David de hecho, supongo que estaba confundido allí mismo, y por un breve momento mezclé la sobrecarga de funciones (que c ++ hace estáticamente) y el despacho múltiple. errare humanum est ...
miraculixx

Respuestas:

12

Los términos significan lo siguiente:

  • despacho estático = el orden de despacho se define en tiempo de compilación . Simplemente significa que cualquier llamada a función / método dice foo()o x.foo()invocará siempre la misma función; esto se establece una vez y luego permanece de esa manera. Esto implica que el compilador puede determinar el tipo de xen tiempo de compilación.

  • despacho dinámico = el pedido de despacho se resuelve en tiempo de ejecución . Esto significa que el compilador construye una tabla de búsqueda de todas las funciones / métodos y determina a cuál llamar realmente en tiempo de ejecución. Digamos que hay clases A y B, que implementan la interfaz X con el método X.bar(). En tiempo de ejecución, yse examina y se basa en su clase real A.bar()o B.bar()se llama.

  • despacho dinámico múltiple = el orden de despacho depende del nombre de función / método + tipos de argumento (= también conocido como firma ), y la implementación real que se llama se determina dinámicamente en tiempo de ejecución. Digamos que la clase A implementa métodos A.fooBar(int)y A.fooBar(char *), y hay una llamada a a.fooBar(x)su programa. Tanto en tiempo de ejecución ay xse examinan y el método real de llamada se determina con base en el tipo de x.

Vea Wikipedia para más información sobre despacho dinámico y despacho dinámico múltiple .

miraculixx
fuente
1
¿Puedo tratar las funciones gratuitas de C ++ que admiten el envío múltiple estático ?
Eonil
bueno, por definición no, el despacho múltiple implica dinámica. Con las funciones gratuitas de c ++, AFAIK el compilador hace todo el trabajo que es realmente un despacho estático que siempre mira el nombre de la función + firma.
miraculixx
1
Si el término despacho se puede usar tanto en estático como dinámico, ¿por qué el despacho múltiple implica dinámico? ¿Qué pasa con el envío múltiple estático ?
Eonil
1
el envío estático significa que el compilador construye una tabla de búsqueda de todas las funciones, incluida la firma. Cualquier despacho estático es efectivamente despacho múltiple, por lo que, por convención, cuando dices despacho múltiple, las personas supondrán que eres dinámico .
miraculixx
@miraculixx No todo el envío estático es envío múltiple. Ese es el caso en C ++ pero no en general.
user253751
12

Mi consejo aquí es: no pienses demasiado en este. Despacho simplemente significa enviar. Enviar un evento a un oyente, enviar una interrupción a un controlador, enviar un mensaje a un receptor, enviar una llamada a un procedimiento o función: todos los aspectos del mismo concepto básico. Envíe los datos al código que lo manejará. Resolución significa elegir entre los destinos disponibles, y es solo una parte del envío.

En términos de código, el envío comienza con algún tipo de paquete de información y algo que indica dónde debe enviarse, y finaliza cuando el paquete se ha enviado (enviado). Todos los idiomas tienen algún tipo de mecanismo de despacho incorporado, pero muchos implementan esquemas de resolución y despacho para satisfacer un propósito único. El manejo de interrupciones y el procesamiento de mensajes de Windows son ejemplos que vienen a la mente.

C ++ puede usar resolución estática o dinámica, pero si elige entre funciones basadas en tipos de argumentos, solo puede hacerlo en tiempo de compilación. Smalltalk / Objective C y Ruby resuelven despachos en tiempo de ejecución, al igual que muchos lenguajes dinámicos.

Despacho único significa que se considera un único argumento como el receptor y determina qué método se llama. El método está típicamente en la clase para ese objeto receptor, y la firma del método se convierte en un desplazamiento en una tabla de despacho (vtable) en esa clase. El objeto privilegiado en C ++ es el anterior al punto, que se convierte en el puntero 'this'.

El envío múltiple significa que no hay un receptor con privilegios, pero generalmente es una operación de coincidencia de patrones en todos los tipos de argumentos. El sistema de objetos Common Lisp utiliza este enfoque. Ver https://en.wikipedia.org/wiki/Multiple_dispatch .

En C ++ con operadores sobrecargados, A + B y B + A deben despacharse a diferentes métodos. En CLOS pueden ser lo mismo.

Probablemente prefiera el término MultiMethods, ya que es una resolución de múltiples factores en lugar de un despacho múltiple per se. Ver http://c2.com/cgi/wiki?MultiMethods . También http://www.codeproject.com/Articles/242749/Multiple-dispatch-and-double-dispatch .

david.pfx
fuente
1
"C ++ puede usar resolución estática o dinámica ... solo puede hacerlo en tiempo de compilación", ¿qué pasa con los métodos virtuales? Esos se determinan dinámicamente en tiempo de ejecución y dependen de la firma del método
miraculixx
Espero que mi edición aclare lo que pretendía.
david.pfx
0

C ++ no tiene despacho múltiple (dinámico). Considera lo siguiente:

#include <iostream>

struct Foo {
   virtual ~Foo() {}
};

struct FooOne : public Foo {};

struct Bar {
   virtual ~Bar() {}
   virtual void dispatch (const Foo &) {
      std::cout << "Bar::Dispatch(const Foo &)\n";
   }
};

struct BarOne : public Bar {
   using Bar::dispatch;
   virtual void dispatch (const Foo &) {
      std::cout << "BarOne::Dispatch(const Foo &)\n";
   }
   virtual void dispatch (const FooOne &) {
      std::cout << "BarOne::Dispatch(const FooOne &)\n";
   }
};

void process (Bar & bar, const Foo & foo) {
   bar.dispatch (foo);
}

int main () {
   Foo foo;
   Bar bar;
   FooOne foo_one;
   BarOne bar_one;

   process (bar, foo);
   process (bar, foo_one);

   process (bar_one, foo);
   process (bar_one, foo_one);

   bar_one.dispatch (foo_one);

   return 0;
}

La salida de lo anterior es

Bar::Dispatch(const Foo &)
Bar::Dispatch(const Foo &)
BarOne::Dispatch(const Foo &)
BarOne::Dispatch(const Foo &)
BarOne::Dispatch(const FooOne &)

Dentro process(Foo& foo, const Bar& bar), C ++ usa el despacho dinámico en el argumento fooen la declaración foo.dispatch(bar). Las líneas de salida tercera y cuarta muestran este despacho dinámico de estilo C ++ en acción. La cuarta línea de salida demuestra que C ++ no tiene despacho múltiple. Si lo hiciera, esa cuarta línea de salida sería la misma que la última.

Esa linea final? Eso es despacho estático. El compilador sabe en tiempo de compilación exactamente qué función debe llamarse. Esta última llamada no pasa por la tabla virtual.

David Hammen
fuente
El ejemplo es válido y útil, pero el envío múltiple, también conocido como métodos múltiples, va más allá. En un lenguaje que se envía a un receptor de clase única, ni siquiera puede escribir el tipo de ejemplo que viene naturalmente en CLOS.
david.pfx