Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Массив разных объектов-наследников (pointers?)


Автор: KasMP 16.7.2009, 16:34
Доброе время суток снова, мои замечательные винградовцы 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) не появляются и просто опускаются...

Как можно на лету узнать тип (с этим мы справимся - в файле написано) и создать именно такой элемент массива? Не могу догадаться...

Автор: azesmcar 16.7.2009, 16:47
Цитата(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();
}

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

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

Автор: Леопольд 16.7.2009, 19:00
Цитата(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.

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

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

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

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

Автор: Леопольд 16.7.2009, 19:33
Цитата(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.

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

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

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

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

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

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

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

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

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

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

Автор: Леопольд 16.7.2009, 19:51
Цитата(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

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

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

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

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

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

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

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

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

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

А надо скрывать что это патерны smile Ну, можно без шаблонов реализовать, но этот ей использовать легче будет.

Автор: KasMP 17.7.2009, 07:49
Ух ты, сколько тут всего написали 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 .

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

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

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

Автор: azesmcar 17.7.2009, 08:53
Цитата(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 

Автор: Andrew121 17.7.2009, 09:01
Прошу прощения за оффтоп.
В этом: http://forum.vingrad.ru/index.php?showtopic=266893&view=findpost&p=1923072 посте я насчитал 13 смайликов. Значит довольна. Не зря старались smile 

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

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

Проблема в том что map можно менять, при этом, например, все итераторы, которые уже на что-то указывают, становятся невалидными. Можно доработать эту фабрику так, что-бы она работала безопасно с точки зрения многопоточности, не меняя внешнего интерфейса. Но здесь это точно ни к чему, как и singleton. Я упомянул о нём, для того что бы показать что может быть некоторое количество проектных решений одной и той же задачи. После освоения С++ классов, стоит уделить внимание ООП. Сам С++ только предоставляет свои средства для этого. Я в своё время не придавал этому особого значения, а зря, потому что понимая ООП, перестаешь просто пользоваться классами, полиморфизмом и т.п. а начинаешь использовать возможности языка целенаправленно, заранее спроектировав систему. Насколько я вижу, KasMP сначала кодирует, а потом уже пытается сложить все части вместе. Наоборот, сложнее, но гораздо эффективнее. Книжка GoF невелика и читается легко (как мне показалось). Я прочёл её за две недели, а она перевернула мое представление о том как надо создавать программы.

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

Добавлено @ 09:26
Цитата(azesmcar @ 17.7.2009,  08:53)
Ну, о шаблонах в книгах для новичков практически ничего не написано.

По шаблонам, и их возможностям на сегодняшний день, есть книжка "Шаблоны С++. Справочник разработчика" 538 стр. А5
Как раз её я сейчас прочёл наполовину smile

Автор: azesmcar 17.7.2009, 09:38
Цитата(Леопольд @  17.7.2009,  09:21 Найти цитируемый пост)
Можно доработать эту фабрику так, что-бы она работала безопасно с точки зрения многопоточности

зачем? если можно просто не делать ее синглтоном smile 

Цитата(Леопольд @  17.7.2009,  09:21 Найти цитируемый пост)
А если объект не меняет своего состояния за время жизни, то он безопасен.

потоко-безопасен. Ответ: скорее всего - да, (в общем случае - нет). Речь идет о контейнерах STL, а thread safety guarantee STL контейнеры не дают. Надо смотреть доки конкретной реализации STL. Гарантию на потоко-безопасное чтение дает реализация STL от SGI. В общем случае - такой гарантии нет.

Автор: Леопольд 17.7.2009, 09:49
Цитата(azesmcar @ 17.7.2009,  09:38)
Цитата(Леопольд @  17.7.2009,  09:21 Найти цитируемый пост)
Можно доработать эту фабрику так, что-бы она работала безопасно с точки зрения многопоточности

зачем? если можно просто не делать ее синглтоном smile

5000 потоков могу использовать одну, разделяемую, фабрику. 
Кстати, можно ли её вынести в динамически подключаемую либу? Я с этим не разбирался, и не знаю, как шарится память между разными программами.

Автор: azesmcar 17.7.2009, 09:53
Цитата(Леопольд @  17.7.2009,  09:49 Найти цитируемый пост)
Кстати, можно ли её вынести в динамически подключаемую либу? Я с этим не разбирался, и не знаю, как шарится память между разными программами

нет, нельзя, шаблонные классы в динамическую библиотеку не помещаются.

Цитата(Леопольд @  17.7.2009,  09:49 Найти цитируемый пост)
5000 потоков могу использовать одну, разделяемую, фабрику. 

чего?

Автор: Леопольд 17.7.2009, 09:59
Цитата(azesmcar @ 17.7.2009,  09:53)
нет, нельзя, шаблонные классы в динамическую библиотеку не помещаются.

А если она будет не шаблонная?

Автор: azesmcar 17.7.2009, 10:00
Цитата(Леопольд @  17.7.2009,  09:59 Найти цитируемый пост)
А если она будет не шаблонная? 

можно

Автор: Леопольд 17.7.2009, 10:00
Цитата(azesmcar @ 17.7.2009,  09:53)
Цитата(Леопольд @  17.7.2009,  09:49 Найти цитируемый пост)
5000 потоков могу использовать одну, разделяемую, фабрику. 

чего?

Цифра, конечно, нереальная, для обычных ситуаций smile

Например, нам надо порождать ISUP сообщения, а каждое соединение обрабатывается в отдельном потоке. Я работаю, в основном, с MSC (Mobile Switching Center)  smile 

Автор: Леопольд 17.7.2009, 16:10
Цитата(Леопольд @ 17.7.2009,  09:21)
По шаблонам, и их возможностям на сегодняшний день, есть книжка "Шаблоны С++. Справочник разработчика" 538 стр. А5
Как раз её я сейчас прочёл наполовину smile

Что они творят! Вот пример, из книги, немножко переделан, для наглядности:

Код

#include <iostream>

template <typename Base, int D>
class Discriminator: public Base{
};
template <typename Setter1, typename Setter2,
          typename Setter3>
class PolicySelector: public Discriminator<Setter1,1>,
                      public Discriminator<Setter2,2>,
                      public Discriminator<Setter3,3>{
};

struct DefaultPolicy1{
    static void func(void){ std::cout<<"DefaultPolicy1"<<std::endl; }
}; 
struct DefaultPolicy2{
    static void func(void){ std::cout<<"DefaultPolicy2"<<std::endl; }
}; 
struct DefaultPolicy3{
    static void func(void){ std::cout<<"DefaultPolicy3"<<std::endl; }
}; 
struct DefaultPolicies{
    typedef DefaultPolicy1 P1;
    typedef DefaultPolicy2 P2;
    typedef DefaultPolicy3 P3;
};
class DefaultPolicyArgs: virtual public DefaultPolicies{
};

template <typename PolicySetter1 = DefaultPolicyArgs,
          typename PolicySetter2 = DefaultPolicyArgs,
          typename PolicySetter3 = DefaultPolicyArgs>
class TemplateWhithUnorderedPolicies{
    typedef PolicySelector <PolicySetter1, PolicySetter2,
                            PolicySetter3>
            Policies;
public:
    static void Call(void){
        Policies::P1::func();
        Policies::P2::func();
        Policies::P3::func();
    }
};

template <typename Policy>
struct Policy1_is: virtual public DefaultPolicies{
    typedef Policy P1;
};

template <typename Policy>
struct Policy2_is: virtual public DefaultPolicies{
    typedef Policy P2;
};

template <typename Policy>
struct Policy3_is: virtual public DefaultPolicies{
    typedef Policy P3;
};


//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

struct CustomPolicy{
    static void func(void){
        std::cout<<"CustomPolicy"<<std::endl;
    }
};

int main(int argc, char* argv[])
{
    TemplateWhithUnorderedPolicies<Policy2_is<CustomPolicy> >::Call();
    return 0;
}


Автор: azesmcar 17.7.2009, 16:12
Цитата(Леопольд @  17.7.2009,  16:10 Найти цитируемый пост)
Что они творят! Вот пример, из книги, немножко переделан, для наглядности:

ну и что они творят?

Автор: Леопольд 17.7.2009, 16:25
Цитата(azesmcar @ 17.7.2009,  16:12)
Цитата(Леопольд @  17.7.2009,  16:10 Найти цитируемый пост)
Что они творят! Вот пример, из книги, немножко переделан, для наглядности:

ну и что они творят?

Можно задавать параметры шаблона в любом порядке, при этом остальные останутся по умолчанию. Я был впечатлён. Настолько, что решил поделиться smile и забыл объяснить...

Код

   TemplateWhithUnorderedPolicies<Policy3_is<CustomPolicy>, Policy1_is<CustomPolicy> >::Call();

Автор: KasMP 18.7.2009, 22:57
Цитата(jonie @  17.7.2009,  08:02 Найти цитируемый пост)
еще есть boost::serialization - готовый к использованию сериализатор\десериализатор с различными форматтерами (простой для использования) раз пошла такая пьянка ....может стоит взглянуть на него. 

Спасибо, учтем на будущее smile .
Цитата(Леопольд @  17.7.2009,  08:19 Найти цитируемый пост)
Мне надо "общаться" только в трезвом состоянии. А то бываю черезчур резок, если спровоцирвать... 

smile
Цитата(azesmcar @  17.7.2009,  08:53 Найти цитируемый пост)
Добавил комментарии (в первом посте). Надеюсь поможет (с английским хорошо?), если что - спрашивайте, не стесняйтесь. 

smile smile. Ваши ценные комментарии я вполне понимаю.
Вопросов пока нет - я пыталась сделать все это более простым способом smile.
Цитата(azesmcar @  17.7.2009,  08:53 Найти цитируемый пост)
Ну, о шаблонах в книгах для новичков практически ничего не написано. 

Ну, в ней есть главы и про шаблоны, и про STL... Хотя не исключено, что для вас это будет "практически ничего" smile .
Цитата(azesmcar @  17.7.2009,  08:53 Найти цитируемый пост)
чтобы глаза не мозолить лишними страницами кода

Посмотрим smile . Спасибо за все хорошее smile smile .
Цитата(Andrew121 @  17.7.2009,  09:01 Найти цитируемый пост)
Прошу прощения за оффтоп.
В этом: http://forum.vingrad.ru/index.php?showtopi...t&p=1923072 посте я насчитал 13 смайликов. Значит довольна. Не зря старались

 smile Ты очень наблюдателен smile smile !
______________________________________________

Пусть есть полиморфный класс Base и производные от него Der, Der1 и Der2. Я хочу уметь приводить переменные типа Base* к типу Der*, Der1* или Der2*.
"Более простой" способ имеет 2 основные составляющие:
  • Base* factory()
    Каким-то способом функция узнает, какой именно объект-наследник от нее хотят получить, и возвращает указатель на него. Например, как-то так:
    Код

    Base* factory (char i) {
     switch (i) {
      case '0': return new Der;
      case '1': return new Der1;
      case '2': return new Der2;
     }
    return 0;
    }

    Здесь вроде как функция должна вернуть указатель соответствующего типа.
  • Если p типа Base* действительно ссылается на объект типа Der, то dynamic_cast может привести p к Der*.
    Как-то так:
    Код

    int main() {
     Base *bp;
     Der *dp, d_ob;

     bp = &d_ob; // bp ссылается на Der
     dp = dynamic_cast <Der*> (bp);

    И вот после этого якобы приведение должно пройти успешно.

Но у меня все совсем по-другому:
На строках типа
Код
  case '1': return new Der;
 и 
Код
bp = &d_ob;
 возникает ошибка
Цитата(VS 2008 Express Edition)

1>... : error C2243: 'type cast' : conversion from 'Der *' to 'Base *' exists, but is inaccessible

smile smile smile

Автор: azesmcar 19.7.2009, 10:40
Цитата(KasMP @  18.7.2009,  22:57 Найти цитируемый пост)
1>... : error C2243: 'type cast' : conversion from 'Der *' to 'Base *' exists, but is inaccessible

Скорее всего результат приватного наследования.
Код

class A {}
class B : A {}; //это приватное наследование, эквивалентно class B : private A {};

надо заменить на
Код

class A {}
class B : public A {};

Автор: GrishinUS 19.7.2009, 15:08
а можно попросить пример с boost::serialization?
в моей программе как раз буст нужно использовать.
И.... как подключить boost к MSVC ?

Автор: azesmcar 19.7.2009, 15:29
Цитата(GrishinUS @  19.7.2009,  15:08 Найти цитируемый пост)
а можно попросить пример с boost::serialization?

http://www.boost.org/doc/libs/1_38_0/libs/serialization/example/demo.cpp

Автор: GrishinUS 19.7.2009, 16:37
спасибо, посмотрел.
Вопросы :

1) Зачем создается класс bus_stop, от него потом наследуются классы bus_stop_corner и bus_stop_destination. Что это дает?
2) смущает комментарий :

Код

class bus_schedule
{
public:
    // note: this structure was made public. because the friend declarations
    // didn't seem to work as expected.
    struct trip_info


почему не работает как ожидалось? Это баг? Если да, то где: в boost или stdlib?

3) создается все-таки фиксированное число экземпляров:

Код

    // fill in the data
    // make a few stops
    bus_stop *bs0 = new bus_stop_corner(
        gps_position(34, 135, 52.560f),
        gps_position(134, 22, 78.30f),
        "24th Street", "10th Avenue"
    );
    bus_stop *bs1 = new bus_stop_corner(
        gps_position(35, 137, 23.456f),
        gps_position(133, 35, 54.12f),
        "State street", "Cathedral Vista Lane"
    );
    bus_stop *bs2 = new bus_stop_destination(
        gps_position(35, 136, 15.456f),
        gps_position(133, 32, 15.300f),
        "White House"
    );
    bus_stop *bs3 = new bus_stop_destination(
        gps_position(35, 134, 48.789f),
        gps_position(133, 32, 16.230f),
        "Lincoln Memorial"
    );
...
    delete bs0;
    delete bs1;
    delete bs2;
    delete bs3;


 а мне нужно создать заранее неопределенное кол-во экземпляров (в моем случае, объектов может быть максимум 25), как это лучше оформить?

4) вопрос, который меня больше всего интересует, где лучше сделать создание и наполнение экземпляров данными из исходного файла? У меня была идея вынести процедуры загрузки исходных данных вообще в отдельный объект, правда в таком случае не понятно каким образом передавать созданные экземпляры в main.

Автор: KasMP 27.8.2009, 17:05
Цитата(azesmcar @  19.7.2009,  10:40 Найти цитируемый пост)
Скорее всего результат приватного наследования.

Телепат smile  smile ! Это была правда smile .
Спасибо за прекрасную приятную помощь smile smile .

GrishinUS, я не знаю ответы на твои вопросы, к сожалению smile smile,

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