2010-05-30 17 views
15

Ich muss ein Programm schreiben, die Visitor Design Pattern implementieren. Das Problem besteht darin, dass die Basis-Besucherklasse eine Vorlagenklasse ist. Das bedeutet, dass BaseVisited :: accept() eine Template-Klasse als Parameter verwendet und da sie 'this' verwendet und ich 'this' brauche, um auf die richtige Laufzeitinstanz des Objekts zu zeigen, muss sie auch virtuell sein.
Ich würde gerne wissen, ob es ein Problem gibt.benötigen eine virtuelle Vorlage Mitglied Problemumgehung

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

Was ist daran falsch? –

+2

wird nicht kompiliert. http://stackoverflow.com/questions/2354210/template-member-function-virtual – yurib

+2

Compiler akzeptiert keine Vorlagen in virtuellen Funktionen. – Puppy

Antwort

16

Sie sollten den BaseVisitor trennen.

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); 
}; 

Wenn Sie BaseVisited der abgeleiteten Klassen müssen auch als Templat zu sein und ihre richtigen Typen Bestanden/Überlastungen zu besuchen, sind Sie offiziell tot.

+0

Sie haben mich dazu geschlagen! :-) –

+3

Grundsätzlich ist dies [Typ löschen] (http://stackoverflow.com/questions/2354210/template-member-function-virtual/2354671#2354671). – sbi

+0

Ich denke, ich könnte offiziell tot sein ... :-P – NargothBond

4

Ich kam mit etwas etwas anders als DeadMG up:

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(); 
}; 

-Mine eine zusätzliche result() Member-Funktion, die Sie abrufen das Ergebnis des letzten Besuchs läßt.

+0

Ich glaube nicht, dass dies funktioniert –

4

Sie können virtuelle Vorlagen nicht deklarieren/definieren. Der Grund dafür ist, dass der virtuelle Dispatch-Mechanismus bekannt sein muss, wenn der Compiler die Definition der Basisklasse sieht, die Templates jedoch bei Bedarf kompiliert werden.

Bei der allgemeinen vtable-Implementierung besteht das Problem, dass die Anzahl der Einträge, die der Compiler für die virtuelle Funktion reservieren muss, undefiniert ist (wie viele verschiedene Instanziierungen des Typs kann es geben?), Ebenso wie deren Reihenfolge . Wenn Sie die Klasse deklarieren:

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

Der Compiler zwei Einträge in der VTable für die Zeiger auf foo und bar in der VTable behalten kann und die VTable perfekt ist nur durch Prüfung der Klassendefinition definiert. Dies kann mit Vorlagenfunktionen nicht erreicht werden.

+0

Ich weiß, dass es unmöglich ist und ich verstehe warum, meine Frage war über eine Lösung, die keine Vorlage virtuelle Funktion beinhaltet . danke trotzdem. – yurib

+0

@Yurib: Sie möchten eine Lösung und haben Ihr Problem noch nicht angegeben - Ich habe das in einem Kommentar zu der Frage gefragt: Was wollen Sie wirklich erreichen? Sie haben nur nach einer möglichen Lösung gefragt, die nicht funktioniert, nicht nach dem ursprünglichen Problem. –

Verwandte Themen