2010-07-16 10 views
7

ho scritto il modello di visitatore come segue ma non capisco cosa sia la spedizione singola e doppia. AFAIK, la singola spedizione richiama un metodo basato sul tipo di chiamante in cui il doppio invio richiama un metodo basato sul tipo di chiamante e sul tipo di argomento.Che cos'è la spedizione singola e doppia?

Suppongo che la doppia spedizione avvenga in una gerarchia di classi singole, ma perché la classe visitatore ha due gerarchia di classi ma è ancora considerata come doppia spedizione.

void floppyDisk::accept(equipmentVisitor* visitor) 
{ 
visitor->visitFloppyDisk(this); 
} 

void processor::accept(equipmentVisitor* visitor) 
{ 
visitor->visitProcessor(this); 
} 

void computer::accept(equipmentVisitor* visitor) 
{ 
BOOST_FOREACH(equipment* anEquip, cont) 
{ 
    anEquip->accept(visitor); 
} 

visitor->visitComputer(this); 
} 

void visitFloppyDisk(floppyDisk*); 
void visitProcessor(processor*); 
void visitComputer(computer*); 

Spiegare utilizzando il codice di esempio fornito.

AFAIK, la prima spedizione è avvenuta su oggetti che invocano l'accettazione e la seconda spedizione su oggetti che invocano il metodo di visita.

Grazie.

+0

Forse la lettura di questo [articolo ] (http://en.wikipedia.org/wiki/Multiple_dispatch) può aiutarti a capire il dispatch - non come è implementato in C++, ma il concetto –

risposta

9

In breve, l'invio singolo è quando un metodo è polimorfico sul tipo di un parametro (incluso l'implicito this). La doppia spedizione è il polimorfismo su due parametri.

L'esempio tipico per il primo è un metodo virtuale standard, che è polimorfico sul tipo dell'oggetto contenente. E il secondo può essere implementato tramite il pattern Visitor.

[aggiornamento] assumo che nel tuo esempio, floppyDisk, processor e computer ogni ereditano da una classe base comune che definisce accept come metodo virtuale. Allo stesso modo, i metodi visit* devono essere dichiarati virtuali in equipmentVisitor, che dovrebbe avere alcune classi derivate con diverse implementazioni visit*. [/ aggiornamento]

Supponendo quanto sopra, accept è polimorfica sia this e equipmentVisitor. Floppydisk, processore e computer hanno ciascuno la propria implementazione di accept, quindi quando il visitatore chiama accept, la posta viene inviata in base al tipo di chiamata. Quindi il chiamato richiama il metodo di visita specifico del tipo del visitatore e questa chiamata viene inviata in base al tipo effettivo del visitatore. In teoria ci può essere anche una tripla, una quadrupla, ecc., Anche se non l'ho mai visto implementato nella pratica (in lingue che non supportano il doppio e le spedizioni più alte per natura, cioè - Mi sembra di ricordare che Smalltalk lo fa?). Il doppio invio di Visitor in C++ e lingue simili è già abbastanza di per sé sorprendente, quindi l'implementazione di dispatch tripli e superiori sarebbe semplicemente troppo complicata per essere utilizzata in applicazioni reali.

+1

+1, l'invio multiplo in lingue che non lo supportano in modo nativo implica manualmente scrittura tutte le combinazioni e cresce in modo esponenziale con il numero di argomenti da inviare, il che è un buon motivo per cercare di evitarlo. –

6

Nel tuo esempio, ti mancano le basi del meccanismo: ereditarietà e virtualità. Supponiamo la seguente gerarchia di classe, oltre al codice:

class equipmentVisited 
{ 
    virtual void accept(equipmentVisitor* visitor) = 0; 
} 

class floppyDisk : public equipmentVisited 
{ 
    virtual void accept(equipmentVisitor* visitor); 
} 

class processor : public equipmentVisited 
{ 
    virtual void accept(equipmentVisitor* visitor); 
} 

class computer : public equipmentVisited 
{ 
    virtual void accept(equipmentVisitor* visitor); 
} 

class equipmentVisitor 
{ 
    virtual void visitFloppyDisk(floppyDisk*); 
    virtual void visitProcessor(processor*); 
    virtual void visitComputer(computer*); 
} 

// Some additional classes inheriting from equipmentVisitor would be here 

Ora, immaginate di avere questo pezzo di codice in qualche funzione:

equipmentVisited* visited; 
equipmentVisitor* visitor; 
// ... 
// Here you initialise visited and visitor in any convenient way 
// ... 
visited->accept(visitor); 

Grazie al meccanismo di doppia spedizione, quest'ultima linea consente a qualsiasi equipmentVisited di accettare qualsiasi equipmentVisitor, indipendentemente dal loro tipo statico reale. Alla fine, verrà chiamata la giusta funzione per la classe giusta.

In sintesi:

  • Il primo dispaccio chiama accept() sulla classe appropriata
  • La seconda spedizione chiama la funzione appropriata sulla classe selezionata dalla prima spedizione
Problemi correlati