НУЖНО реализовать ассоциотивный контейнер, такой, что он может хранить обьекты любых типов, но возвращать значение можно только зная его тип. Только по id, не зная типа получить его невозможно.
Здравствуйте alex_shar, Вы писали:
AS>НУЖНО реализовать ассоциотивный контейнер, такой, что он может хранить обьекты любых типов, но возвращать значение можно только зная его тип. Только по id, не зная типа получить его невозможно.
Во-первых, зачем именно такая постановка задачи?
Во-вторых, данные каких типов предполагается хранить (все — это слишком общо)
числа
указатели на числа
указатели на структуры, массивы (сюда же можно отнести С-строки)
указатели на объекты
указатели на ком-объекты
варианты
и так далее.
Для каждого случая есть свой механизм распознавания типа.
Наиболее общий, хотя и геморройный способ — хранить варианты (VARIANT) и на попытку чтения проверять соответствие типа. Способ не пригоден для не-комовских объектов.
В-третьих, как предполагается оформлять отказ?
подсовывать значение по умолчанию
возвращать код ошибки
бросать исключение
В-четвертых, возможно ли, чтобы одному ключу соответствовал "букет" (несколько значений разных типов), или же один ключ — одно данное? Что происходит при повторной записи по одному ключу значения другого типа?
В-пятых, какая конверсия типов возможна?
все типы различны (int != long)
целые типы с точностью до размера и знака (int == long != unsigned != short != char)
целые типы эквивалентны, вещественные эквивалентны
(для классов) записанный объект субкласса (наследник) эквивалентен запрашиваему суперклассу (предку)
(для ком-объектов) запрашивается интерфейс; если объект его имеет — удача
(для диспинтерфейсов) запрашивается свойство или метод
В-шестых, можно ли для объектов безымянного типа (тип не идентифицируется средствами RTTI языка, например, перечисление, массив или структура) указывать тип "вручную"
setValue("key", "MyStructure", new MyStruc);
getValue("key", "MyStructure", (void**)&pMyStruc) --> true
getValue("key", "SomethingElse", (void**)&pXXX) --> false
(в принципе, так работает COM)
Наконец, какой инструментарий предполагается использовать?
голый С
STL
MFC
COM
Если вы делаете библиотеку, то какой инструментарий наиболее подходит для стыковки с другими модулями?
А>Полный вариант задания таков:
А>Реализовать контейнерный класс, обладающий следующими свойствами
А>1. Класс представляет собой ассоциативный контейнер, способный хранить объекты произвольных типов, используя строки или другой тип идентификатора в качестве ключей.
А>2. В одном контейнере могут храниться объекты разных типов. При этом доступ к объектам – type-safe, то есть объект класса A можно получить только как объект класса A. Получение объекта по имени(id), не зная его типа невозможно.
А>...
А>5. Элегантный интерфейс, такого образца:
А>Container C1, C2;
А>int i = 5;
А>A a;
А>B b;
А>C1[“Int”] = i;
А>C1[“Obj1”] = a;
А>C1[“Obj2”] = b;
А>C1[“Ptr”] = &a;
А>C2[“Copy”] = C1[“Obj1”];
А>A* anotherA = C1[“Ptr”];
А>B b2 = C1[“Obj2”];
Простейшее решение — использовать некий "универсальный" тип наподобие VARIANT в COM. А весь typesafe-доступ реализовывать посредством перегрузки операторов. Правда, для хранения объектов, т.е. экземпляров классов, придется помучиться, поскольку в С++ нет универсального способа создания копии объекта. Можно потребовать, чтобы все классы реализовывали функцию для копирования
class IContainerObject { // Функции, необходимые для хранения объекта в контейнере
public:
virtual ~IContainerObject();
virtual IContainerObject* Clone() const = 0; // Создание копии объекта
virtual const char* GetTypeName() const = 0; // Возвращает имя типа объекта, вместо этой функции можно использовать RTTI
};
class MyClass: virtual public IContainerObject {
public:
...
virtual TContainerObject* Clone() const { ... }
...
};
Айрат.