2016-08-06 12 views
-2

bekam ich einen Code wie folgt:std :: vector mit einem Template-Argument

template<class T> void Engine::extend(std::string name) { 
    T *instance = new T(this); 
    this->newExtensions[name] = instance; 
} 

es in einer solchen Art und Weise genannt:

engine.extend<Menu>("menu"); 

Es funktioniert perfekt, aber ich möchte erstellen eine neue Instanz von T später in meinem Code (in Hauptschleife meines Spiels), anstatt das in Engine::extend Methode zu tun. Ist es möglich, eine Information über die Klasse beizubehalten, die in einem Vektor oder irgendeiner anderen Datenstruktur instanziiert werden soll, die über die gesamte Klasse Engine geteilt wird, so kann ich sie später in einer anderen Methode aufrufen? Pseudo-Code von dem, was ich zu erreichen versuchen:

template<class T> void Engine::extend(std::string name) { 
    this->newExtensions[name] = T; 
} 
+0

was "newExtensions"? –

+0

Ich verstehe nicht ganz, was ist die Art von 'this-> newExtensions'? –

+0

Entschuldigung, das ist eine Karte. – solusipse

Antwort

1

die Typen tun, dass Sie eine gemeinsame Basis schaffen wird? Als Wie in C++ können Sie keine Sammlung (Vektor/Map) nicht verwandten Typ haben, sollten Typen eine gemeinsame Basisklasse für den folgenden Code zu arbeiten haben. (Sie können aber void * verwenden, aber Konvertierungen nicht sicher sein):

#include <iostream> 
#include <map> 

class Entity { 
    public: 
    virtual ~Entity(){} 
}; 

class C1: public Entity 
{ 
    public: 
    void doSomething(){std::cout << "C1" << std::endl;} 
}; 

class C2: public Entity 
{ 
    public: 
    void doSomething(){std::cout << "C2" << std::endl;} 
}; 

class C3 
{ 
    public: 
    void doSomething(){std::cout << "C3" << std::endl;} 
}; 



class CreatorBase { 
    public: 
     virtual ~CreatorBase() {}; 
     virtual Entity* create() = 0; 
}; 

template<typename T> 
class Creator: public CreatorBase { 
    public: 
     Entity* create() 
     { 
      return new T; 
     }  
}; 

std::map<int, CreatorBase*> cmap; 

Hier haben wir eine Klasse Basisentität und C1 und C2 erben von ihm. Als nächstes gibt es die Vorlagenklasse Creator, die ein Objekt des angeforderten Typs erstellt.

Sie alle erben von CreatorBase, sodass sie in einer Karte gespeichert werden können.

Der Ersteller gibt Entity * zurück, und für die Typsicherheit können wir dynamic cast beim Aufrufen von create() verwenden, um sicherzustellen, dass wir den richtigen Typ erstellen.

Wenn Sie nur einen Entity-Pointer benötigen, können Sie Entity * überall verwenden und Dynamic Cast wird nicht benötigt.

int main(int argc, char *argv[]) 
{ 
    cmap[1]=new Creator<C1>; 
    cmap[2]=new Creator<C2>; 
    //cmap[3]=new Creator<C3>; //will not compile - C3 does not derive from Entity 

    C1 *i1 = dynamic_cast<C1*> (cmap[1]->create()); 
    C2 *i2 = dynamic_cast<C2*> (cmap[2]->create()); 
    C1 *i3 = dynamic_cast<C1*> (cmap[2]->create()); //bad dynamic cast: cmap[2] does not create C1 

    if (!i1) { 
     std::cout << "i1: Bad dynamic cast" << std::endl; 
    } else {  
     i1->doSomething(); 
    } 

    if (!i2) { 
     std::cout << "i2: Bad dynamic cast" << std::endl; 
    } else {  
     i2->doSomething(); 
    } 

    if (!i3) { 
     std::cout << "i3: Bad dynamic cast" << std::endl; 
    } else { 
      i3->doSomething(); 
    } 
} 

Ausgang:

C1 
C2 
i3: Bad dynamic cast 
+0

Ziemlich kompliziert aber tut genau das, was ich wollte, vielen Dank! – solusipse