Fournisseurs de services C ++
-
03-07-2019 - |
Question
J'ai appris le C ++ à partir de C #, où je me suis habitué à utiliser des fournisseurs de services: en gros un dictionnaire < Type, objet > ;. Malheureusement, je n'arrive pas à comprendre comment faire cela en C ++. Donc, les questions sont essentiellement:
-
Comment créer un dictionnaire en C ++?
-
Comment utiliser "Type" avec, dans la mesure où je sais qu'il n'y a pas de "Type" en C ++.
-
Comme ci-dessus, mais avec 'objet'.
Merci!
La solution
Je suppose que vous essayez de mapper un type sur une instance d'objet unique. Vous pouvez essayer quelque chose dans ce sens:
#include <typeinfo>
#include <map>
#include <string>
using namespace std;
class SomeClass
{
public:
virtual ~SomeClass() {} // virtual function to get a v-table
};
struct type_info_less
{
bool operator() (const std::type_info* lhs, const std::type_info* rhs) const
{
return lhs->before(*rhs) != 0;
}
};
class TypeMap
{
typedef map <type_info *, void *, type_info_less> TypenameToObject;
TypenameToObject ObjectMap;
public:
template <typename T>
T *Get () const
{
TypenameToObject::const_iterator iType = ObjectMap.find(&typeid(T));
if (iType == ObjectMap.end())
return NULL;
return reinterpret_cast<T *>(iType->second);
}
template <typename T>
void Set(T *value)
{
ObjectMap[&typeid(T)] = reinterpret_cast<void *>(value);
}
};
int main()
{
TypeMap Services;
Services.Set<SomeClass>(new SomeClass());
SomeClass *x = Services.Get<SomeClass>();
}
En C ++, les types ne sont pas des objets de première classe à part entière, mais au moins le nom du type va être unique, vous pouvez donc y entrer.
Éditer: les noms ne sont pas vraiment uniques, donc gardez les pointeurs type_info et utilisez la méthode before pour les comparer.
Autres conseils
Vous voudrez probablement consulter le modèle de carte STL . C ++ a certainement des types (difficile d’avoir un héritage sans lui), mais pas de définition spécifique & "Type &"; classe.
La STL a deux conteneurs associatifs: std::map<K,V> and
std :: multimap. Il y a aussi std::set<V>
qui devrait être un adaptateur de std::map<V,void>
, mais en tant que tel, ce n'est pas un conteneur associatif. La carte multiple est similaire à la carte, mais elle autorise plusieurs clés identiques dans le même conteneur. Les éléments map et multimap contiennent tous deux des éléments de type std::pair<K,V>
. En d'autres termes, std::map<K,V>::value_type == std::pair<K,V>
, mais std::map<K,V>::key_type == K
et std::map<K,V>::mapped_type == V
.
En ce qui concerne & "Tapez &", je ne suis pas tout à fait sûr de ce que vous voulez dire. Si vous voulez parler de classes paramétrées, C ++ appelle cette & "Programmation de modèles &" Ou & "Programmation générique &"; Dans ce qui précède, std::map<K,V>
est paramétré sur K et V pour le type de clé et le type de valeur. C ++ prend également en charge les fonctions de modèle:
template<typename T>
void f(T o);
déclarera une fonction qui prend en paramètre n'importe quel type, y compris les types primitifs. C ++ ne prend pas en charge la résolution de type générique, de sorte que le type T doit appartenir à une certaine hiérarchie. Pour le moment, tout ce que vous pouvez faire est de supposer que le type passé appartient bien à la hiérarchie correcte, et le compilateur se plaindra si vous essayez d'appeler une fonction non déclarée sur un objet de ce type.
template<typename T>
void f(T o) {
o.do_it();
}
Ce qui précède fonctionne tant que T définit la méthode do_it()
.
Un dictionnaire me ressemble à une carte STL: std::map<K, T>
. Jetez un coup d’œil à la bibliothèque de modèles standard: c’est génial. Cela fait partie de ANSI C ++ depuis un moment. Microsoft a une belle implémentation de PJ Plauger, si je me souviens bien.