2016-11-01 3 views
2

Ich habe eine Familie von Klassen, und jede Unterklasse benötigt eine Karte, aber die Schlüssel werden verschiedene Typen haben, obwohl sie beide genau die gleichen Operationen mit der Karte ausführen. Auch der Wert in beiden Fällen wird Zeichenfolge sein. Bisher habe ich Code ähnlich dem unten stehenden Beispiel, mein Ziel ist es, Code wieder zu verwenden, indem einen generischen Schlüssel hat. ohne zusätzliche Bibliotheken neben STLC++ Std :: Map-Klasse mit generischem Schlüssel

class A{ 
public: 
    /* 
    * More code 
    */ 
}; 


class subA1 : public A{ 
public: 
    void insertValue(long id, std::string& value){ 
     if(_theMap.find(id) == _theMap.end()) 
     { 
      _theMap[id] = value; 
     } 
    } 

private: 
    std::map<long,std:string> _theMap; 
}; 

class subA2 : public A{ 
public: 
    void insertValue(std::string& id, std::string& value){ 
     if(_theMap.find(id) == _theMap.end()) 
     { 
      _theMap[id] = value; 
     } 
    } 
private: 
    std::map<std::string,std:string> _theMap; 

}; 
+0

Was meinst du _generic key_? Eine andere Vorlage? Eine 'std :: Variante'? –

+0

Gibt es neben anderen Kartentypen noch weitere Unterschiede zwischen Unterklassen? – balki

+0

balki: Beide Unterklassen führen sehr unterschiedliche Operationen aus, aber das Speichern und Abrufen von Daten in der Map ist identisch und einige andere Codes gemeinsam – ulitosCoder

Antwort

1

Sie subA1 und subA2 in eine einzige Template-Klasse zusammenführen können, zum Beispiel:

class A{ 
public: 
    /* 
    * More code 
    */ 
}; 

template <typename KeyType> 
class subA : public A { 
public: 
    void insertValue(const KeyType &id, const std::string& value) { 
     if(_theMap.find(id) == _theMap.end()) { 
      _theMap.insert(std::make_pair(id, value)); 
     } 
    } 

private: 
    std::map<KeyType, std:string> _theMap; 
}; 

Sie können dann typedefs schaffen je nach Bedarf:

typedef subA<long> subA1; 
typedef subA<std::string> subA2; 

Oder, wenn Sie tatsächlich benötigen abgeleitet Klassen:

class subA1 : public subA<long> 
{ 
    ... 
}; 

class subA2 : public subA<std::string> 
{ 
    ... 
}; 
+0

Ich denke, das ist eine gute Lösung, weil ich Klasse A abstrakt sein muss, da ich nicht weiß, welche spezifische Unterklasseninstanz ich bis zur Laufzeit erstellen werde. – ulitosCoder

0

Wie wäre es eine weitere kleine Basisklasse zu schreiben, sagen C<T>, die ein template typename T und enthält nur eine map<T, string> und Ihre insert Funktion. Dann wird jede neue Unterklasse von A auch eine Unterklasse von C sein. Ihr subA1 wird public A, public C<long> usw.

2

Einfach Superklasse A eine Vorlage, verschieben Sie sowohl _theMap und insertValue(), und verwenden Sie die richtige Template-Version in Unterklassen.

template <typename KeyT> 
class A{ 
public: 
    void insertValue(KeyT id, std::string& value){ 
     if(_theMap.find(id) == _theMap.end()) 
     { 
      _theMap[id] = value; 
     } 
    } 

private: 
    std::map<KeyT, std:string> _theMap; 
}; 

class subA1 : public A<long> {}; 

class subA2 : public A<std::string> {}; 
+0

Abhängig von der tatsächlichen Beziehung zwischen 'A',' subA1' und 'subA2', kann es sinnvoll sein,' subA1' und 'subA2' in eine einzelne Vorlage' subA' zusammenzufassen, die das enthält 'map' und leitet sich von Nicht-Template' A' ab. –

+0

Er sagte in einem Kommentar, dass "beide Unterklassen sehr unterschiedliche Operationen ausführen, aber das Speichern und Abrufen von Daten in der Karte ist identisch". –