AFAIK, der Begriff Versand bedeutet nur eine Methodenauflösung und einen Aufruf. Es spielt keine Rolle, ob es statisch oder dynamisch ist. Ich habe gesehen, dass viele Leute einen Begriff wie statischen Versand und dynamischen Versand verwenden .
Was mich verwirrt, ist, dass es auch einige mysteriöse Beschreibungen gibt. Ich habe versucht zu verstehen, was Mehrfachversand ist , und es scheint, als würde nur ein Unterprogramm nach Parametertypen ausgewählt . Wenn ich es richtig verstanden habe, kann es sowohl statischen Mehrfachversand als auch dynamischen Mehrfachversand geben , und wir können sagen, dass C ++ Mehrfachversand über kostenlose Funktionen bereitstellt .
In einem Wikipedia-Artikel über Mehrfachversand heißt es jedoch, dass C ++ keinen Mehrfachversand hat, da es keine dynamische Auflösung der Funktion durch mehrere Parameter hat. Und ich bekomme wirklich keinen konzeptionellen Unterschied zwischen dem Common Lisp-Beispiel und der überladenen C ++ - Funktion. Weil ich keinen konzeptionellen Unterschied finden kann, wenn der Begriff Mehrfachversand keinen dynamischen Versand impliziert . Und mir wurde klar, dass ich verwirrend bin, was der Versand wirklich ist
Ich habe auch den QS-Eintrag Multiple Dispatch vs. Function Overloading überprüft , und es scheint, dass die Antwort davon ausgeht, dass der Begriff Dispatch grundsätzlich dynamisch ist . Das macht mich auch verwirrend.
Was bedeutet der Begriff Versand richtig ? Bedeutet dies eine dynamische Auflösung ? Ist dieser Begriff gut definiert oder nur konventionell? Was vermisse ich?
quelle
Antworten:
Die Begriffe bedeuten Folgendes:
statischer Versand = Der Versandauftrag wird zur Kompilierungszeit definiert . Es bedeutet einfach, dass jeder Funktions- / Methodenaufruf immer dieselbe Funktion aufruft
foo()
oderx.foo()
aufruft - dies wird einmal eingerichtet und bleibt dann so. Dies bedeutet, dass der Compiler den Typx
zur Kompilierungszeit bestimmen kann .dynamischer Versand = Der Versandauftrag wird zur Laufzeit aufgelöst . Dies bedeutet, dass der Compiler eine Nachschlagetabelle aller Funktionen / Methoden erstellt und festlegt, welche zur Laufzeit tatsächlich aufgerufen werden soll. Angenommen, es gibt Klasse A und B, die beide die Schnittstelle X mit der Methode implementieren
X.bar()
. Wird zur Laufzeity
geprüft und basiert entweder auf seiner tatsächlichen KlasseA.bar()
oderB.bar()
wird aufgerufen.mehrfacher dynamischer Versand = Die Versandreihenfolge ist abhängig von Funktions- / Methodenname + Argumenttypen (= auch als Signatur bezeichnet ), und die tatsächliche Implementierung, die aufgerufen wird, wird zur Laufzeit dynamisch bestimmt . Angenommen, Klasse A implementiert Methoden
A.fooBar(int)
undA.fooBar(char *)
, unda.fooBar(x)
in Ihrem Programm wird aufgerufen . Zur Laufzeit werden beidea
undx
geprüft und die tatsächlich aufzurufende Methode anhand des Typs von bestimmtx
.Weitere Informationen zum dynamischen Versand und zum mehrfachen dynamischen Versand finden Sie in Wikipedia .
quelle
Mein Rat hier ist: Überdenken Sie diesen nicht. Versand bedeutet einfach senden. Versenden Sie ein Ereignis an einen Listener, senden Sie einen Interrupt an einen Handler, senden Sie eine Nachricht an einen Empfänger, senden Sie einen Aufruf an eine Prozedur oder Funktion: alle Aspekte desselben Grundkonzepts. Senden Sie die Daten an den Code, der sie verarbeitet. Auflösung bedeutet die Wahl zwischen verfügbaren Zielen und ist nur ein Teil des Versands.
In Bezug auf den Code beginnt der Versand mit einer Art Informationspaket und etwas, das angibt, wohin es gesendet werden soll, und endet, wenn das Paket gesendet (versendet) wurde. In allen Sprachen ist eine Art Versandmechanismus integriert, aber viele implementieren Auflösungs- und Versandschemata, um einem bestimmten Zweck gerecht zu werden. Interrupt-Behandlung und Windows-Nachrichtenverarbeitung sind Beispiele, die mir in den Sinn kommen.
C ++ kann eine statische oder dynamische Auflösung verwenden. Wenn jedoch Funktionen basierend auf Argumenttypen ausgewählt werden, kann dies nur zur Kompilierungszeit erfolgen. Smalltalk / Objective C und Ruby lösen Versendungen zur Laufzeit auf, ebenso wie viele dynamische Sprachen.
Einzelversand bedeutet, dass ein einzelnes Argument als Empfänger betrachtet wird und bestimmt, welche Methode aufgerufen wird. Die Methode befindet sich normalerweise in der Klasse für dieses Empfängerobjekt, und die Methodensignatur wird in einen Versatz in einer Versandtabelle (vtable) in dieser Klasse konvertiert. Das privilegierte Objekt in C ++ ist das vor dem Punkt, der zum 'this'-Zeiger wird.
Mehrfachversand bedeutet keinen privilegierten Empfänger, sondern normalerweise eine Mustervergleichsoperation über alle Argumenttypen hinweg. Das Common Lisp Object System verwendet diesen Ansatz. Siehe https://en.wikipedia.org/wiki/Multiple_dispatch .
In C ++ mit überladenen Operatoren müssen A + B und B + A an verschiedene Methoden gesendet werden. In CLOS können sie gleich sein.
Ich bevorzuge wahrscheinlich den Begriff MultiMethods, da es sich eher um eine Multi-Faktor-Auflösung als um einen Mehrfachversand an sich handelt. Siehe http://c2.com/cgi/wiki?MultiMethods . Auch http://www.codeproject.com/Articles/242749/Multiple-dispatch-and-double-dispatch .
quelle
C ++ hat keinen mehrfachen (dynamischen) Versand. Folgendes berücksichtigen:
Die Ausgabe von oben ist
Innerhalb von
process(Foo& foo, const Bar& bar)
C ++ wirdfoo
in der Anweisung ein dynamischer Versand für Argumente verwendetfoo.dispatch(bar)
. Die dritte und vierte Ausgabezeile zeigen diesen dynamischen Versand im C ++ - Stil in Aktion. Die vierte Ausgabezeile zeigt, dass C ++ keinen Mehrfachversand hat. Wenn dies der Fall wäre, wäre diese vierte Ausgabezeile dieselbe wie die letzte.Diese letzte Zeile? Das ist statischer Versand. Der Compiler weiß zur Kompilierungszeit genau, welche Funktion aufgerufen werden muss. Dieser letzte Aufruf geht nicht durch die virtuelle Tabelle.
quelle