2011-01-17 5 views
2

Ich habe keine Ahnung, ob der Titel einen Sinn ergibt, aber ich finde nicht die richtigen Worte, um mein "Problem" in einer Zeile zu beschreiben. Wie auch immer, hier ist mein Problem. Es gibt eine Schnittstelle für eine Suche:Geben Sie bei der Instanziierung einer abgeleiteten Klasse einen Basisklassen-Vorlagenparameter an?

template <typename InputType, typename ResultType> class Search { 
public: 
    virtual void search (InputType) = 0; 
    virtual void getResult(ResultType&) = 0; 

}; 

und mehrere abgeleitete Klassen wie:

template <typename InputType, typename ResultType> 
    class XMLSearch : public Search<InputType, ResultType> { 
public: 
    void search (InputType) { ... }; 
    void getResult(ResultType&) { ... }; 

}; 

Die abgeleiteten Klassen werden später im Quelltext verwendet werden. Ich möchte einen einfachen Zeiger auf eine Search halten, ohne die Template-Parameter spezifiziert, dann einen neuen XMLSearch zuweisen und damit die Template-Parameter der Suche zu definieren und XMLSearch

Search *s = new XMLSearch<int, int>(); 

ich einen Weg gefunden, die syntaktisch funktioniert wie das, was ich Ich versuche zu tun, aber es scheint ein bisschen seltsam, es wirklich zu verwenden:

template <typename T> class Derived; 

class Base { 
public: 
template <typename T> 
bool GetValue(T &value) { 
    Derived<T> *castedThis=dynamic_cast<Derived<T>* >(this); 
    if(castedThis) 
    return castedThis->GetValue(value); 
    return false; 
} 
virtual void Dummy() {} 
}; 

template <typename T> class Derived : public Base { 
public: 
Derived<T>() { 
    mValue=17; 
} 

bool GetValue(T &value) { 
    value=mValue; 
    return true; 
} 
T mValue; 
}; 

int main(int argc, char* argv[]) 
{ 
Base *v=new Derived<int>; 
int i=0; 
if(!v->GetValue(i)) 
    std::cout<<"Wrong type int."<<std::endl; 
float f=0.0; 
if(!v->GetValue(f)) 
    std::cout<<"Wrong type float."<<std::endl; 
std::cout<<i<<std::endl<<f; 
char c; 
std::cin>>c; 
return 0; 
} 

Gibt es einen besseren Weg, dies zu erreichen?

Antwort

1

Gibt es einen besseren Weg, dies zu erreichen?

Ja, das Design ist etwas besser, denn das ist mit statisch-Dispatching beim Aufruf GetValue() (Ich gehe davon aus, dass dynamic_cast Tippfehler sind, man wollte eigentlich static_cast in Base::GetValue() eingeben). In diesem Design ist Base::GetValue() nicht virtuell, aber es ist in der Lage, Derived::GetValue() unter Verwendung Zeiger des Typs Base aufzurufen. Dies macht es etwas schnell.

Aber auch dein Weg ist nicht so schlimm.

Search<int,int> *s = new XMLSearch<int, int>(); 

Ihre Search *s = new XMLSearch<int, int>() ist falsch: Alles, was Sie haben Ihre Klassenvorlagen wie folgt zu instanziiert!


Sie können Ihre Vorlagen typedef wie folgt:

typedef Search<int,int> iisearch; 
typedef XMLSearch<int,int> iixmlsearch; 

sie dann verwenden:

iisearch *s = new iixmlsearch(); 

Das sieht besser aus, nicht wahr?


Kleine Änderung

Sie können Ihre Klasse etwas bessere Performance-weise machen. Dazu Ihre Suche Klassenvorlage wie folgt schreiben:

template <typename InputType, typename ResultType> class Search { 
public: 
    void search (InputType input) //it's not virtual anymore! 
    { 
     xmlsearch *_this = getXmlSearch(); 
     xmlsearch->search(input); 
    } 
    void getResult(ResultType& result) //it's not virtual anymore! 
    { 
     xmlsearch *_this = getXmlSearch(); 
     xmlsearch->getResult(result); 
    } 
private: 
    typedef XMLSearch<InputType, ResultType> xmlsearch; 
    xmlsearch* getXmlSearch() 
    { 
     static xmlsearch *_this= static_cast<xmlsearch* >(this); 
     return _this; 
    } 

}; 

Jetzt ist Ihre Basisklasse nicht abstrakt ist, da es keine virtuellen Funktionen definieren. Dieses Design ist etwas schneller als deine Version!

Verwandte Themen