Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Массив разных объектов-наследников (pointers?), тип заранее не известен, чтение из файла 
V
    Опции темы
KasMP
Дата 16.7.2009, 16:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: нет
Всего: 30



Доброе время суток снова, мои замечательные винградовцы smile !

Предполагается уже знакомая многим структура базовых и производных классов (указываю только защищенные члены, содержащие данные - в функциях ничего интересного нет; есть чисто виртуальные функции; color - выше определенная структура: struct color (r,g,b;)):
  • Figure {color fpen;}
    • Point {POINT p;}
    • Line {POINT p1, p2;}
    • FilledFigure {color fbrush; RECT rect;}
      • Ellipse
      • Rectangle
        (Ellipse и Rectangle разделены, т.к. у них будет разная реализация функций рисования и проверки принадлежности точки с заданными координатами фигуре)

В файле удобным для нас (и соответствующим иерархии классов) образом заданы фигуры типов Point, Line, Ellipse, Rectangle (но сам порядок перечисления фигур мы менять не можем, мы можем выбрать только способ задания конкретной фигуры); можно указать и общее количество фигур. Например, как-то так:
Цитата

n
point [RGB для пера] x y
line [RGB для пера] x1 y1 x2 y2
ellipse [RGB для пера] [RGB для кисти] [4 числа прямоугольника, в который вписан эллипс]
rectangle [RGB для пера] [RGB для кисти] [RECT]

Цитата

2
point 0 0 0 4 5
ellipse 34 34 65 234 231 198 4 3 6 8

Как несложно увидеть, мы знаем только общее количество фигур и не знаем заранее ни тип следующей фигуры, ни общее число фигур какого-то типа.

Собственно, в чем проблема...
Надо "просто" создать их этих объектов-фигур какую-то ... массивообразную структуру (т.е. так, чтобы с помощь индекса от 0 до n-1 мы могли обратиться к любому объекту, прочитать содержимое его членов, изменить его, поменять местами с каким-то другим элементом с известным номером).
Понятно, что все это связано с указателями на базовый класс - это основы динамического полиморфизма.

Можно было бы разбить файл на 4 условных части (сначала кол-во Point и их описания, потом кол-во Line и их описания, потом ... ) и создать 4 массива... Но это уже слишком упрощает задачу программиста и резко ограничивает свободу пользователя в выборе z-order-а фигур (предполагается, что изначально фигуры накладываются друг на друга в том порядке, в котором читаются; порядок сохраняется в бинарное дерево (как именно, я пока не думала) и потом может изменяться).

Я думала
создать массив из указателей на Figure (должно получиться - размер одного указателя известен, а знать размер наследника Figure (или самого Figure) нам не нужно)
узнать тип следующей фигуры
взять временную переменную такого типа, прочитать в нее данные из файла
скопировать данные этой переменной туда, куда показывает указатель текущего цикла

Но, естественно, ничего не получилось: указатель-то на Figure и копируются только те члены, которые есть в Figure, а специальные уточняющие члены (точки для Point и Line, цвет кисти и прямоугольник для FilledFigure) не появляются и просто опускаются...

Как можно на лету узнать тип (с этим мы справимся - в файле написано) и создать именно такой элемент массива? Не могу догадаться...
PM MAIL   Вверх
azesmcar
Дата 16.7.2009, 16:47 (ссылка) |    (голосов:5) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата(KasMP @  16.7.2009,  16:34 Найти цитируемый пост)
Как можно на лету узнать тип (с этим мы справимся - в файле написано) и создать именно такой элемент массива? Не могу догадаться... 

Factory?
Код

#include <string>
#include <map>

namespace patterns {
    template <class baseT>
    class Factory
    {
    private:
        // object creator base non-template interface (to keep in container)
        class IObjectCreator {
        public:
            virtual baseT* Create() = 0;
        };

        // concrete object creator template class
        template <class T>
        class ConcreteObjectCreator: public IObjectCreator {
        public:
            virtual baseT* Create() {
                return new T();
            }
        };
    public:
        // default constructor
        Factory() {}
        // destructor
        ~Factory() {
            // delete all created object creators
            for (typename ContainerType::const_iterator it = container_.begin(); it != container_.end(); ++it)
                delete (it->second);
        }
        // register given type
        template <class T>
        void RegisterType(const std::string& name) {
            // try to register type and check wheter the type is already registered
            if ( !container_.insert( ContainerType::value_type( name, new ConcreteObjectCreator<T>() ) ).second )
                throw std::runtime_error("Type is arleady registered");
        }
        // create object by given type
        baseT* Create(const std::string& name) {
            // try to found registered type creator object
            ContainerType::const_iterator it = container_.find( name );
            // if found
            if (it != container_.end())
                // create object and return pointer it's pointer
                return it->second->Create();
            // if not found - throw an exception
            throw std::runtime_error( "Type is not registered" );
        }
    private:
        typedef std::map<std::string, IObjectCreator*> ContainerType;

        // associative container for mapping type name and creator object
        ContainerType container_;
    };
};


Код

#include <iostream>

class Base
{
public:
    virtual void foo() = 0;
};

class A : public Base
{
public:
    virtual void foo() { std::cout << "A" << std::endl; }
};

class B : public Base
{
public:
    virtual void foo() { std::cout << "B" << std::endl; }
};

class C : public Base
{
public:
    virtual void foo() { std::cout << "C" << std::endl; }
};

int main()
{
    patterns::Factory<Base> factory;

    //register types
    factory.RegisterType<A>("A");
    factory.RegisterType<B>("B");
    factory.RegisterType<C>("C");

    Base* aPtr = factory.Create("A");
    aPtr->foo();
}

пример использования.

убрал использование умных указателей

Это сообщение отредактировал(а) azesmcar - 17.7.2009, 08:43
PM   Вверх
Леопольд
Дата 16.7.2009, 19:00 (ссылка) |    (голосов:4) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 3
Всего: 13



Цитата(azesmcar @ 16.7.2009,  16:47)
Код

class Base
{
public:
    virtual void foo() = 0;
};

Я добавил бы виртуальный деструктор в Base, на случай, если будущие наследники освобождают память в деструкторе. Особенно если учесть отказ от "умных" указателей.
Код

class Base
{
public:
    virtual void foo() = 0;
    virtual ~Base(){}
};


Мне кажется, что Factory желательно оформить как singleton.

Это сообщение отредактировал(а) Леопольд - 16.7.2009, 19:02


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
azesmcar
Дата 16.7.2009, 19:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата(Леопольд @  16.7.2009,  19:00 Найти цитируемый пост)
Я добавил бы виртуальный деструктор в Base, на случай, если будущие наследники освобождают память в деструкторе. Особенно если учесть отказ от "умных" указателей.

Это всего лишь пример написаный на скорую руку, думаю что использование виртуального деструктора здесь очевидно.
А умные указатели убрал чтобы топикстартеру было легче понять код и чтобы потом не мучалась с хранением auto_ptr -а (именно он был использован как default smart pointer в параметре шаблона) в контейнере.

Цитата(Леопольд @  16.7.2009,  19:00 Найти цитируемый пост)
Мне кажется, что Factory желательно оформить как singleton.

С чего это? А если потом две фабрики понадобиться весь код менять? Нафиг надо.

Это сообщение отредактировал(а) azesmcar - 16.7.2009, 19:15
PM   Вверх
Леопольд
Дата 16.7.2009, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 3
Всего: 13



Цитата(azesmcar @ 16.7.2009,  19:14)
Цитата(Леопольд @  16.7.2009,  19:00 Найти цитируемый пост)
Мне кажется, что Factory желательно оформить как singleton.

С чего это? А если потом две фабрики понадобиться весь код менять? Нафиг надо.

Если это будут две разные фабрики 
patterns::Factory<Base> factoryB;
patterns::Factory<AnotherBase> factoryA;
То это не проблема. А зачем две одинаковых? Проблема может быть из-за того что это не чистая фабрика, она ещё и память чистит. Я бы вынес это из фабрики. И пользовался бы shared_ptr<Base> в качестве возвращаемого значения Create.

Это сообщение отредактировал(а) Леопольд - 16.7.2009, 19:37


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
mes
Дата 16.7.2009, 19:42 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(azesmcar @  16.7.2009,  18:14 Найти цитируемый пост)
Это всего лишь пример написаный на скорую руку, 

т.с. будет сильно рада. Вопрос в разделе новичков  и сразу шаблонами по голове.  smile 

KasMP, В общем для реализации обычной фабрики, о которой шла речь выше, надо несколько Create-функций (одинаковой сигнатуры), поместить в (ассоциативный) массив и потом по названию/индексу вызывать подходящую функцию. Create-функцию зачастую удобно оформлять как статическую в классе, объект которого она создает.

Добавлено @ 19:44
Цитата(Леопольд @  16.7.2009,  18:00 Найти цитируемый пост)

Мне кажется, что Factory желательно оформить как singleton.

синглетоны следует применять только тогда, когда они необходимы..(т.е. нет другого варианта или он проблематичен). Одним словом не стоит ими сильно увлекаться smile

Это сообщение отредактировал(а) mes - 16.7.2009, 19:45


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 16.7.2009, 19:44 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата(Леопольд @  16.7.2009,  19:33 Найти цитируемый пост)
То это не проблема. А зачем две одинаковых? 

Может понадобиться. Например в многопоточном приложении.

Цитата(mes @  16.7.2009,  19:42 Найти цитируемый пост)
т.с. будет сильно рада. Вопрос в разделе новичков  и сразу шаблонами по голове.  smile 

Эти фабрики...они такие smile 


Это сообщение отредактировал(а) azesmcar - 16.7.2009, 19:48
PM   Вверх
Леопольд
Дата 16.7.2009, 19:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 3
Всего: 13



Цитата(azesmcar @ 16.7.2009,  19:44)
Цитата(Леопольд @  16.7.2009,  19:33 Найти цитируемый пост)
То это не проблема. А зачем две одинаковых? 

Может понадобиться. Например в многопоточном приложении.

Если она только "плодит" объекты, то вроде нет проблем...

Добавлено через 1 минуту и 3 секунды
Цитата(azesmcar @ 16.7.2009,  19:44)
Цитата(mes @  16.7.2009,  19:42 Найти цитируемый пост)
т.с. будет сильно рада. Вопрос в разделе новичков  и сразу шаблонами по голове.  smile 

Эти фабрики...они такие smile

Мне кажется что shared_ptr тоже достаточно прост. smile


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
Леопольд
Дата 16.7.2009, 20:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 3
Всего: 13



Цитата(Леопольд @ 16.7.2009,  19:33)
Проблема может быть из-за того что это не чистая фабрика, она ещё и память чистит.

Показалось что она ещё и удаляет все созданные ей объекты. Был неправ, каюсь...  smile 


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
mes
Дата 16.7.2009, 20:46 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(azesmcar @  16.7.2009,  18:44 Найти цитируемый пост)

Эти фабрики...они такие smile 

с таким подходом у новичков можно вызвать страх и отвращение к паттернам. Хотя на самом деле большинство и них элементарны по сути.
 smile 


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 16.7.2009, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата(Леопольд @  16.7.2009,  19:51 Найти цитируемый пост)
Если она только "плодит" объекты, то вроде нет проблем...

Проблема есть. Поищи в гугле std::map thread safety issues.

Цитата(mes @  16.7.2009,  20:46 Найти цитируемый пост)

с таким подходом у новичков можно вызвать страх и отвращение к паттернам. Хотя на самом деле большинство и них элементарны по сути.
 smile  

А надо скрывать что это патерны smile Ну, можно без шаблонов реализовать, но этот ей использовать легче будет.
PM   Вверх
KasMP
Дата 17.7.2009, 07:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: нет
Всего: 30



Ух ты, сколько тут всего написали smile . Да еще подумали, чтобы мне было понятно и хорошо smile . Как приятно smile  smile ...
Цитата(azesmcar @  16.7.2009,  19:44 Найти цитируемый пост)
Эти фабрики...они такие 

Цитата(mes @  16.7.2009,  19:42 Найти цитируемый пост)
т.с. будет сильно рада. Вопрос в разделе новичков  и сразу шаблонами по голове.

Цитата(mes @  16.7.2009,  20:46 Найти цитируемый пост)
с таким подходом у новичков можно вызвать страх и отвращение к паттернам. Хотя на самом деле большинство и них элементарны по сути.

Вообще говоря, с шаблонами у меня все не так плохо и страшно, как можно подумать smile  smile . Надо только немного повторить и освежить...
Цитата(mes @  16.7.2009,  19:42 Найти цитируемый пост)
KasMP, В общем для реализации обычной фабрики, о которой шла речь выше, надо несколько Create-функций (одинаковой сигнатуры), поместить в (ассоциативный) массив и потом по названию/индексу вызывать подходящую функцию. Create-функцию зачастую удобно оформлять как статическую в классе, объект которого она создает.

Как всегда, мне понятно каждое слово и вообще понятно. Благодарю smile .
Цитата(azesmcar @  16.7.2009,  21:42 Найти цитируемый пост)
А надо скрывать что это патерны smile Ну, можно без шаблонов реализовать, но этот ей использовать легче будет. 

Я вчера увидела у Герберта Шилдта главу 22 с гордым названием "динамическая идентификация типа и операторы приведения" (удивительно, что заметить ее раньше я не смогла smile). Сначала он торжественно описывает, как появлялась RTTI, как она важна и насколько полезна, потом начинает с typeid() и класса type_info, потом ... пока не знаю. Но если пролистать главу, то "template" видно лишь в самом конце и совсем чуть-чуть: в пункте "применение dynamic_cast к шаблонным классам". Вот smile.
Цитата(azesmcar @  16.7.2009,  19:14 Найти цитируемый пост)
Это всего лишь пример написаный на скорую руку, думаю что использование виртуального деструктора здесь очевидно.

Да, понятно smile .
Цитата(azesmcar @  16.7.2009,  19:14 Найти цитируемый пост)
А умные указатели убрал чтобы топикстартеру было легче понять код и чтобы потом не мучалась с хранением auto_ptr -а (именно он был использован как default smart pointer в параметре шаблона) в контейнере.

Спасибо smile, вот это действительно стоило сделать.
Правда, можно было бы не убирать совсем, а оставить 2 варианта smile .

Леопольд, странно, что репутация у тебя такая отрицательная (а репа даже в "-1" уже настораживает форумчан). Спасибо за все твои старания smile .
PM MAIL   Вверх
jonie
Дата 17.7.2009, 08:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



еще есть boost::serialization - готовый к использованию сериализатор\десериализатор с различными форматтерами (простой для использования) раз пошла такая пьянка ....может стоит взглянуть на него.


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Леопольд
Дата 17.7.2009, 08:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 3
Всего: 13



Цитата(KasMP @ 17.7.2009,  07:49)
Леопольд, странно, что репутация у тебя такая отрицательная (а репа даже в "-1" уже настораживает форумчан).

Мне надо "общаться" только в трезвом состоянии. А то бываю черезчур резок, если спровоцирвать... smile

Это сообщение отредактировал(а) Леопольд - 17.7.2009, 08:44


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
azesmcar
Дата 17.7.2009, 08:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата(KasMP @  17.7.2009,  07:49 Найти цитируемый пост)
Вообще говоря, с шаблонами у меня все не так плохо и страшно, как можно подумать smile  smile . Надо только немного повторить и освежить...

Добавил комментарии (в первом посте). Надеюсь поможет (с английским хорошо?), если что - спрашивайте, не стесняйтесь. 

Цитата(KasMP @  17.7.2009,  07:49 Найти цитируемый пост)
Я вчера увидела у Герберта Шилдта главу 22 с гордым названием "динамическая идентификация типа и операторы приведения" (удивительно, что заметить ее раньше я не смогла smile). Сначала он торжественно описывает, как появлялась RTTI, как она важна и насколько полезна, потом начинает с typeid() и класса type_info, потом ... пока не знаю. Но если пролистать главу, то "template" видно лишь в самом конце и совсем чуть-чуть: в пункте "применение dynamic_cast к шаблонным классам". Вот smile.

Ну, о шаблонах в книгах для новичков практически ничего не написано. 

Цитата(KasMP @  17.7.2009,  07:49 Найти цитируемый пост)
Спасибо smile, вот это действительно стоило сделать.
Правда, можно было бы не убирать совсем, а оставить 2 варианта smile .

Тут была тема про совмещение умных указателей и фабрики.

http://forum.vingrad.ru/forum/topic-250892/hl/factory/0.html
чтобы глаза не мозолить лишними страницами кода smile 
PM   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1116 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.