2009-11-17 14 views
29

Ich versuche zu verstehen, was mehrere Versand ist. Ich lese viele verschiedene Texte, aber ich habe immer noch keine Ahnung, was eine Mehrfachsendung ist und wofür sie gut ist. Vielleicht ist die Sache, die ich vermisse, ein Stück Code, der mehrere Sendungen verwendet. Bitte, können Sie ein kleines Stück Code in C++ mit mehreren Versand schreiben, so dass ich sehe, kann es nicht ordnungsgemäß kompiliert/laufen, weil C++ nur einzelne Versand hat? Ich muss den Unterschied sehen. Vielen Dank.Mehrere Versand in C++

+2

C++ nicht direkt unterstützt, aber ich bin sicher, dass Sie das irgendwie emulieren kann. Ich habe nie MD benutzt oder sogar ein schönes Design in anderen Sprachen gesehen, das mich dazu gebracht hätte, MD in C++ zu haben. Dylan-Fanboys listen es als eine der Sprachfunktionen von Dylan auf. Aber soweit ich das beurteilen kann, riecht es nach einem schlechten Design, weil die Anzahl der Funktionen, die Sie schreiben müssen, exponentiell ansteigt. Ich würde nicht so viele Funktionen schreiben wollen. – sellibitze

+4

Sie haben MD zu jeder Zeit verwendet, wenn Sie das 'Visitor'-Muster verwendet haben. –

+1

Ein einfaches Beispiel mit C++ 11: http://ideone.com/lTsc7M – Jarod42

Antwort

54

Multiversand ist die Möglichkeit, basierend auf dem Laufzeittyp der an den Funktionsaufruf übergebenen Argumente auszuwählen, welche Version einer Funktion aufgerufen werden soll.

Hier ist ein Beispiel, das nicht direkt in C++ funktionieren (ungetestet):

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 für den Code, die das Problem eindeutig angeben – neuro

+1

Danke, diese Antwort ist so ziemlich, was ich sehen musste.Jetzt muss ich nur herausfinden, warum zum Teufel jemand so etwas braucht. Wie auch immer, danke für ein gutes Beispiel. – Martin

+3

Eine Anwendung ist Physik, ein Würfel kollidiert mit einem anderen Würfel ist ein Schnittpunkt, ein Würfel kollidiert mit einer Ebene ist ein anderer Schnittpunkt. Daher haben Sie verschiedene Methoden zur Kollisionserkennung, und das Dispatching ist dafür sehr nützlich. Heres ein Thread auf Doppelversand, http://www.gamedev.net/topic/453624-double-dispatch-in-c/ – QuantumKarl

18

Multiple Dispatch ist, wenn die Funktion, die auf dem Laufzeittyp von mehr als einem Objekt abhängt ausgeführt wird.

C++ hat single dispatch, denn wenn Sie virtuelle Funktionen verwenden, hängt die tatsächliche Funktion, die ausgeführt wird, nur vom Laufzeittyp des Objekts links von dem -> oder ab. Operator.

Ich habe Mühe, an einen echten Programmierfall für den Mehrfachversand zu denken. Vielleicht in einem Spiel, wo verschiedene Charaktere gegeneinander kämpfen.

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

Der Sieger eines Kampfes auf die Eigenschaften beider Gegner abhängen kann, so können Sie diesen Aufruf zu einer der folgenden versenden wollen, auf die Laufzeittypen beider Argumente abhängig:

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. 

Die Funktion hängt von den beiden Argumenten ab, nicht nur von einem. In C++ müssen Sie dies möglicherweise als virtuelle Funktionen schreiben. Eine virtuelle Funktion würde abhängig von einem Argument (dem this-Zeiger) ausgewählt werden. Dann muss die virtuelle Funktion möglicherweise einen Schalter oder etwas enthalten, um etwas speziell mit dem anderen Argument zu tun.

+2

+1 für die Namen ;-) – neuro

+4

Ich vermisse Piraten. Aber ok, danke zum Beispiel. – Martin

+3

Ein praktisches, häufig vorkommendes Beispiel besteht darin, verschiedene Unterklassen anders als ein Array von Basisklassenzeigern zu behandeln. – kizzx2

3

In Einzelversand hängt die ausgeführte Funktion nur vom Objekttyp ab. In doppelten Versand hängt die ausgeführte Funktion vom Objekttyp und einem Parameter ab.

Im folgenden Beispiel wird die Funktion Area() verwendet aufgerufen Einzelversand und Intersect() verlässt sich auf Doppel-Ausgabe, da es eine Form Parameter nimmt.

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*/ } 
}; 

Das Beispiel basiert auf diesem article.

+0

+1 interessanter Link – neuro

+0

Eine ziemlich große Menge von Räumen, die Sie dort haben. – strager

+1

@strager 2 zusätzliche Leerzeichen :) Es wäre schön, wenn Stack Overflow es formatieren könnte, wie viele Räume der Betrachter bevorzugt. – pilkch

11

Sehen Sie dieses Papier von B. Stroustrup geschrieben: Open Multi-Methods for C++

+1

obwohl ich ein +1 gab, sollten Sie eine Zusammenfassung für diesen Artikel setzen ... Auch der Artikel behandelt nur die überschreibende Methode, nicht die ganzen mehrfachen Versandfälle. –