2010-05-30 14 views
15

Ho bisogno di scrivere un programma che implementa il modello di progettazione del visitatore. Il problema è che la classe visitatore base è una classe template. Ciò significa che BaseVisited :: accept() accetta una classe template come parametro e poiché utilizza 'this' e ho bisogno di 'this' per puntare all'istanza runtime corretta dell'oggetto, deve anche essere virtuale.
Mi piacerebbe sapere se c'è un modo per aggirare questo problema.necessario un membro del modello virtuale workaround

template <typename T> 
class BaseVisitor { 
    public: 
    BaseVisitor(); 
    T visit(BaseVisited *visited); 
    virtual ~BaseVisitor(); 
} 


class BaseVisited { 
    BaseVisited(); 
    template <typename T> 
    virtual void accept(BaseVisitor<T> *visitor) { visitor->visit(this); }; // problem 
    virtual ~BaseVisited(); 
} 
+1

Cosa c'è di sbagliato in questo? –

+2

non verrà compilato. http://stackoverflow.com/questions/2354210/template-member-function-virtual – yurib

+2

Il compilatore non accetta i modelli nelle funzioni virtuali. – Puppy

risposta

16

Quello che dovresti fare è separare il BaseVisitor.

class BaseVisited; 
class BaseVisitorInternal { 
public: 
    virtual void visit(BaseVisited*) = 0; 
    virtual ~BaseVisitorInternal() {} 
}; 
class BaseVisited { 
    BaseVisited(); 
    virtual void accept(BaseVisitorInternal* visitor) { visitor->visit(this); } 
}; 
template<typename T> class BaseVisitor : public BaseVisitorInternal { 
    void visit(BaseVisited* visited); 
}; 

Se avete bisogno di classi derivate di BaseVisited essere basato su modelli troppo e superare i loro tipi corretti/Sovraccarichi da visitare, si è ufficialmente morto.

+0

Mi hai battuto! :-) –

+3

Fondamentalmente, questo è [tipo cancellato] (http://stackoverflow.com/questions/2354210/template-member-function-virtual/2354671#2354671). – sbi

+0

Penso che potrei essere ufficialmente morto ... :-P – NargothBond

4

mi si avvicinò con qualcosa di leggermente diverso rispetto DeadMG:

class BaseVisited; 

class IVisitor { 
    public: 
    virtual void visit(BaseVisited *visited) = 0; 
    virtual ~IVisitor(); 
}; 

template <typename T> 
class BaseVisitor : public IVisitor { 
    public: 
    BaseVisitor(); 
    virtual void visit(BaseVisited *visited); 
    virtual ~BaseVisitor(); 
    virtual T result(); 
}; 


class BaseVisited { 
    public: 
    BaseVisited(); 
    virtual void accept(IVisitor *visitor) { visitor->visit(this); }; 
    virtual ~BaseVisited(); 
}; 

Il mio ha un supplemento di funzione di result() membro che consente di recuperare il risultato dell'ultima visita.

+0

Non penso che funzionerà –

4

Non è possibile dichiarare/definire funzioni virtuali basate su modelli. Il motivo è che il meccanismo di invio virtuale deve essere noto quando il compilatore vede la definizione della classe base, ma i modelli vengono compilati su richiesta.

Con l'implementazione di vtable comune il problema è che il numero di voci che il compilatore dovrebbe riservare per la funzione virtuale non è definito (quante diverse istanze del tipo possono esserci?), Come è l'ordine di esse . Se si dichiara la classe:

class base { 
public: 
    virtual void foo(); 
    virtual int bar(); 
}; 

Il compilatore può riservare due voci nel vtable per i puntatori ai foo e bar nel vtable, e il vtable è perfettamente definito, semplicemente controllando la definizione della classe. Questo non può essere ottenuto con le funzioni basate su modelli.

+0

So che è impossibile e capisco perché, la mia domanda era di trovare una soluzione che non includesse una funzione virtuale di template . grazie comunque. – yurib

+0

@Yurib: vuoi una soluzione e tuttavia non hai indicato il tuo problema - l'ho richiesto in un commento alla domanda: cosa vuoi veramente ottenere. Hai solo chiesto informazioni su una soluzione potenziale che non funziona, non su quale sia il problema originale. –

Problemi correlati