Поставщики услуг C++

Я изучал C++, пришедший из C#, где я привык использовать поставщиков услуг: в основном, словарь‹Тип, объект›. К сожалению, я не могу понять, как это сделать на C++. Итак, вопросы в основном:

  1. Как бы я сделал словарь на С++.

  2. Как бы я использовал с ним «Тип», насколько я знаю, в С++ нет «Типа».

  3. То же, что и выше, но с «объектом».

Спасибо!


person Sean James    schedule 05.01.2009    source источник


Ответы (4)


Я предполагаю, что вы пытаетесь сопоставить тип с одним экземпляром объекта. Вы можете попробовать что-то в этом роде:

#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>();
}

В С++ типы не являются самостоятельными объектами первого класса, но, по крайней мере, имя типа будет уникальным, поэтому вы можете использовать его.

Изменить: на самом деле не гарантируется, что имена будут уникальными, поэтому держитесь за указатели type_info и используйте метод before для их сравнения.

person Eclipse    schedule 05.01.2009
comment
Вместо использования строки вы можете использовать адрес статического свойства каждого класса ServiceProvider. - person Frank Schwieterman; 05.01.2009
comment
Неправильно: typeid(T).name НЕ уникален. typeid(T) имеет оператор == для сравнения объектов typeinfo. См., например. type_info_cmp на tangentsoft.net/mysql++/doc/html/refman/ - person MSalters; 05.01.2009

Возможно, вы захотите взглянуть на шаблон карты STL. С++, безусловно, имеет типы (без него трудно иметь наследование), просто нет определенного определенного класса «Тип».

person ctacke    schedule 05.01.2009

STL имеет два ассоциативных контейнера: std::map<K,V> andstd::multimap. Существует также std::set<V>, который должен быть адаптером std::map<V,void>, но как таковой он не является ассоциативным контейнером. Мультикарта аналогична карте, только позволяет использовать несколько одинаковых ключей в одном контейнере. И карта, и мультикарта содержат элементы типа std::pair<K,V>. Другими словами, std::map<K,V>::value_type == std::pair<K,V>, но std::map<K,V>::key_type == K и std::map<K,V>::mapped_type == V.

Что касается "типа", я не совсем уверен, что вы имеете в виду. Если вы имеете в виду параметризованные классы, то С++ называет это «программированием шаблонов» или «универсальным программированием». В приведенном выше примере std::map<K,V> параметризовано по K и V для типа ключей и типа значений. C++ также поддерживает шаблонные функции:

template<typename T>
void f(T o);

объявит функцию, которая принимает в качестве параметра любой тип вообще, включая примитивные типы. C++ не поддерживает разрешение универсального типа, поэтому тип T должен иметь определенную иерархию. На данный момент все, что вы можете сделать, это просто предположить, что переданный тип действительно имеет правильную иерархию, и компилятор будет жаловаться, если вы попытаетесь вызвать необъявленную функцию для объекта этого типа.

template<typename T>
void f(T o) {
    o.do_it();
}

Вышеприведенное будет работать до тех пор, пока T определяет метод do_it().

person wilhelmtell    schedule 05.01.2009

Для меня словарь звучит как карта STL: std::map<K, T>. Взгляните на стандартную библиотеку шаблонов — она великолепна. Некоторое время он был частью ANSI C++. У Microsoft есть хорошая реализация от PJ Plauger, если я правильно помню.

person duffymo    schedule 05.01.2009
comment
Аннотации шаблона не прошли; следует читать std:map‹K, T› - person duffymo; 05.01.2009