Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Хранение типа объекта в нетипизированном классе


Автор: fear 24.3.2008, 15:51
Каким образом можно и можно ли сохранить тип обекта внутри класса, а затем использовать этот тип для создания объекта? Информацию о типе можно получить с помощью ключевого слова typeid, но как использовать её для создания объекта?

Код

class A
{
  public:
    A():ptr(0) {};
    virtual ~A() {clear();};

    template<typename T>
    void setType(const T &value)
    {
      type = new typeid(value);
    }
    void make()
    {
      clear();
      /*
      создание объекта типа type
      ptr = new *type;
      */
    }
    void clear()
    {
      /*освобождение занимаемой памяти*/
    }

  private:
    type_info *type;
    void *ptr;
};

Автор: Lazin 24.3.2008, 15:56
зачем хранить type_info внутри класса, если можно в любой момент его получить через указатель?

Добавлено через 3 минуты и 6 секунд
кстати этот код работать не будет

Автор: Alek86 24.3.2008, 16:03
если тебе нужно работать с несколькими классами через 1 указатель, то. значит, у них есть что-то общее
приведи их к общему интерфейсу и работай

Автор: vinter 24.3.2008, 16:03
делаешь виртуальный базовый класс, от него делаешь сколько надо потомков, которые тебе нужно создавать.
потом делаешь функцию которая в качестве аргумента принимает какой нить идентификатор(например имя нужного тебе класса), затем в функции ставишь несколько if'ов(switch как вариант с целыми), и возвращаешь new objClassName, который в данный момент необходим. 
p.s тип возвращаемого значения ф-ии это указатель на базовый класс

Автор: JackYF 24.3.2008, 16:07
Цитата(fear @  24.3.2008,  14:51 Найти цитируемый пост)
а затем использовать этот тип для создания объекта? Информацию о типе можно получить с помощью ключевого слова typeid, но как использовать её для создания объекта?

Хочешь странного. Скорее всего, нельзя.
Можно создать указатель на "эталлонный объект" (предварительно создав его), а потом клонировать. Это, кстати, в "Паттернах проектирования" есть, почитай.

Автор: UnrealMan 24.3.2008, 16:30
Цитата(fear @  24.3.2008,  15:51 Найти цитируемый пост)
можно ли сохранить тип обекта внутри класса, а затем использовать этот тип для создания объекта? 

Можно сохранить информацию о типе внутри объекта класса, а затем использовать эту информацию для создания объекта соответствующего типа.

Автор: fear 24.3.2008, 16:41
Цитата(Lazin @ 24.3.2008,  15:56)
зачем хранить type_info внутри класса, если можно в любой момент его получить через указатель?

через какой указатель? класс имеет тип А и нетипизированный указатель

Добавлено через 1 минуту и 18 секунд
Цитата(Lazin @ 24.3.2008,  15:56)
кстати этот код работать не будет

если бы код работал, этой темы не существовало бы...

Добавлено через 4 минуты и 8 секунд
Цитата(Alek86 @ 24.3.2008,  16:03)
если тебе нужно работать с несколькими классами через 1 указатель, то. значит, у них есть что-то общее
приведи их к общему интерфейсу и работай

Alek86, vinter интересен случай когда, передаваемые в класс объекты ни как не связаны

Добавлено через 6 минут и 19 секунд
Цитата(JackYF @ 24.3.2008,  16:07)
Хочешь странного. Скорее всего, нельзя.

хочу получить QVariant (Qt) только средствами стандартной библиотеки

Добавлено через 8 минут и 35 секунд
Цитата(UnrealMan @ 24.3.2008,  16:30)
Можно сохранить информацию о типе внутри объекта класса, а затем использовать эту информацию для создания объекта соответствующего типа.

и как это сделать?

Автор: Alek86 24.3.2008, 17:00
Цитата(fear @  24.3.2008,  16:41 Найти цитируемый пост)
хочу получить QVariant (Qt) только средствами стандартной библиотеки

не http://www.boost.org/doc/html/variant.html ли тебе нужно?

Автор: UnrealMan 24.3.2008, 18:35
Цитата(fear @  24.3.2008,  16:41 Найти цитируемый пост)
и как это сделать?

С помощью шаблонов и виртуальных функций.

Автор: archimed7592 24.3.2008, 19:30
fear, почитай что-нибудь про паттерн "фабрика".
Sample code:
Код

class FactorySingleton
{
   template< class ProductT >
   void registerProduct(const string &type)
   {
       this->factoryMethodsMap.insert(make_pair(type, boost::funcrtion< IProduct *() >(boost::lambda::new_ptr< ProductT >())));
   }
   IProduct *createProduct(const string &type) 
   {
       FactoryMethodsMap::const_iterator it = this->factoryMethodsMap.find(type);
       if (it == this->factoryMethodsMap.end())
            return 0;
       return it->second();
   }
};

int main()
{
  FactorySingleton &factory = FactorySingleton::instance();
  factory.registerProduct< ProductA >("A");
  factory.registerProduct< ProductA >("B");
  // ...
  IProduct *a = factory.createProduct("A");
  IProduct *b = factory.createProduct("B");
  // ...
}

Ессно, что разумнее регистрировать продукты на этапе static initialization, но расписывать лень.

Автор: fear 25.3.2008, 00:29
Цитата(Alek86 @ 24.3.2008,  17:00)
не http://www.boost.org/doc/html/variant.html ли тебе нужно?

boost::variant значительно отличается от QVariant, к тому же интерисует реализация только средствами стандартной библиотеки

Автор: fear 25.3.2008, 00:46
Цитата(UnrealMan @ 24.3.2008,  18:35)
Цитата(fear @  24.3.2008,  16:41 Найти цитируемый пост)
и как это сделать?

С помощью шаблонов и виртуальных функций.

Если речь идёт о реализации предполагающей, что передаваемые функции setType() объекты обязаны иметь общего потомка, то это решение уже обсужлось - оно не интересно. Интересен случай, когда передаваемые функции setType() объекты не зависят друг от друга.
Если же речь идёт о каком-то другом решении, будьте добры, представте фрагмент кода, он лучше любых слов поможет понять о чём идёт речь.

archimed7592, меня интерисует реализация только методами стандартной библиотеки, без использования средств boost.

Автор: mes 25.3.2008, 01:16
ну создал ты объект а что ты потом с ним делать будешь?

а вобше чтоб создать в с++ в рантайме объект по условному имени, надо для каждого объекта иметь функцию создания и иметь словарь в котором каждому условному имени будет соответствовать нужная create-функция.

Автор: archimed7592 25.3.2008, 01:17
Цитата(fear @  25.3.2008,  00:46 Найти цитируемый пост)
archimed7592 меня интерисует реализация только методами стандартной библиотеки, без использования средств boost.

Я тебе лишь идею набросал. Ну замени boost::function своим шаблонным функтором, имитирующим поведение конструктора, но это не труъ, ибо не scalable.

Добавлено через 4 минуты и 12 секунд
Цитата(fear @  25.3.2008,  00:46 Найти цитируемый пост)
Интересен случай, когда передаваемые функции setType() объекты не зависят друг от друга.

Тебе интересен boost::any во всей своей красе. Но он не решает проблемы фабрики(он выступает лишь как контейнер):
Цитата(fear @  24.3.2008,  15:51 Найти цитируемый пост)
но как использовать её для создания объекта?

Создавать объекты ты сможешь только предопределённые(зарегистрированные), причём возвращать тебе придётся void *(ибо общего потомка у них не предполагается).

Автор: UnrealMan 25.3.2008, 01:22
Цитата(fear @  25.3.2008,  00:46 Найти цитируемый пост)
Если речь идёт о реализации предполагающей, что передаваемые функции setType() объекты обязаны иметь общего потомка

Шаблоны как раз позволяют избавиться от этого ограничения.

Код

struct Base
{
    virtual ~Base() {}
    virtual void Create() = 0;
};

template <class T>
    struct Derived : Base
{
    virtual void Create(); // тут создаём объект
}

int main()
{
    Base *p = new Derived<Type>; // запомнили тип
    p->Create(); // создали объект
}

Автор: fear 25.3.2008, 01:38
Цитата(mes @  25.3.2008, 01:16)
ну создал ты объект а что ты потом с ним делать будешь?

буду использовать
Код

    template<typename T>
    T &value()
    {
      return static_cast<T &>(*static_cast<T *>(ptr));
    }

Цитата(mes @  25.3.2008, 01:16)
а вобше чтоб создать в с++ в рантайме объект по условному имени, надо для каждого объекта иметь функцию создания и иметь словарь в котором каждому условному имени будет соответствовать нужная create-функция.

и этот подход видимо - единственный... Только не укладывается в голове, почему если имеется возможность сохранить информацию о типе внутри класса, отсутствует возможность использовать непосредственно эту информацию для создания класса того же типа.

Автор: bsa 25.3.2008, 10:41
fear
Код
class A {};
class B : public A{};
int main()
{
     A *p = new B;
     //как узнать, на объект какого класса указывает p, не изменяя класс A?
     return 0;
}

Автор: fear 25.3.2008, 14:31
bsa, как?

Добавлено через 9 минут и 6 секунд
UnrealMan, спасибо, такой подход решает поставленный вопрос.

Автор: bsa 25.3.2008, 15:06
fear, в том то и дело, что никак. Это я к Только не укладывается в голове, почему если имеется возможность сохранить информацию о типе внутри класса, отсутствует возможность использовать непосредственно эту информацию для создания класса того же типа. Так как в данном случае информация не сохраняется. Чтобы она сохранилась, нужно сделать виртуальный деструктор (ну или другой виртуальный метод, но виртуальный деструктор в любом случае делать надо). А раз есть деструктор, то кто мешает сделать виртуальный метод clone()...
Как вариант, можно фабрику замутить...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)