2016-11-01 3 views
2

У меня есть класс классов, и каждому подклассу требуется карта, но ключи будут иметь разные типы, хотя оба они будут выполнять те же самые операции с картой. Также значение в обоих случаях будет строкой. До сих пор у меня есть код, похожий на приведенный ниже пример, моя цель состоит в том, чтобы повторно использовать код, , имеющий общий ключ. без использования каких-либо дополнительные библиотек, кроме STLC++ std :: класс карты с общим ключом

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

Что значит «generic key_»? Другой шаблон? «Std :: variant»? –

+0

Помимо наличия разных типов карт, существуют ли другие различия между подклассами? – balki

+0

balki: оба подкласса выполняют очень разные операции, но хранилище и поиск данных на карте идентичны, а некоторые другие общие коды – ulitosCoder

ответ

1

Вы можете объединить subA1 и subA2 в один шаблоне класса, например:

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

Вы можете создать определения типов при необходимости:

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

Или, если вам нужны фактические полученными классы:

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

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

Я думаю, что это хорошее решение, потому что мне нужно, чтобы класс A был абстрактным, поскольку я не знаю, какой конкретный экземпляр подкласса я создам до выполнения. – ulitosCoder

0

Как насчет написания другого небольшого базового класса, скажет C<T>, который является template typename T и просто включает в себя map<T, string> и вашу insert функции. Тогда каждый новый подкласс A также будет подклассом C. Таким образом, ваш subA1 будет public A, public C<long> и т. Д.

2

Просто сделайте суперкласс A шаблоном, переместите на него как _theMap, так и insertValue() и используйте правильную версию шаблона в подклассах.

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

В зависимости от фактической взаимосвязи между 'A',' subA1' и 'subA2' может возникнуть смысл вместо этого объединить' subA1' и 'subA2' в один шаблон' subA', который выполняет 'map' и получается из не-шаблона' A'. –

+0

Он сказал в комментарии, что «оба подкласса выполняют очень разные операции, но сохранение и поиск данных на карте идентичны». –