Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > Класс, который содержит |
Автор: Rickert 30.10.2008, 07:30 | ||
Так и не смог реализовать такую вещь: у меня есть класс, в котором должен быть список объектов, с разным кол-вом параметров.
Теперь смысл в следующем: как мне добавлять в список объекты типа demoClass, demoClass2, чтобы потом, внутир classContainer, распозновать их по типу и работать с ними? Придумал только вместо списка делать указатель типа void. |
Автор: Lazin 30.10.2008, 09:01 | ||
в принципе, если ты точно знаешь тип объекта, можно просто привести тип и все |
Автор: mes 30.10.2008, 13:36 |
посмотрите патерн visitor, может подойти для вашей задачи |
Автор: J0ker 30.10.2008, 18:07 | ||
боже мой да забудьте вы уже эти касты во-первых, как правильно заметил mes, есть паттерн visitor для сложных вещей. для простых вполне достаточно полиморфизма:
|
Автор: Lycifer 7.11.2008, 13:43 |
Базовый класс имеет такое: enum typeClass{typeBaseClass,typeClassChildren1,typeClassChildren2} class baseClass { protected: baseClass(){}//можно все перегрузить дабы не кто не создал объект этого класса кроме наследников public: virtual typeClass getType(){return typeBaseClass;} }; Реализация наследников class ClassChildren1 : baseClass { typeClass getType(){typeClassChildren1;} }; class ClassChildren2 : baseClass { typeClass getType(){typeClassChildren2;} }; Используется: void SomeFunctionClassChildren1(ClassChildren1 obj) { } void SomeFunctionClassChildren2(ClassChildren2 obj) { } void SomeFunction(baseClass obj) { switch(obj. getType()) { case typeClassChildren1: SomeFunctionClassChildren1((ClassChildren1)obj);//здесь можно и явное приведение break; case typeClassChildren1: SomeFunctionClassChildren2((ClassChildren2)obj);//здесь можно и явное приведение break; default: assert(false); } } } |
Автор: mes 7.11.2008, 14:29 | ||
да уж... ![]() |
Автор: mes 7.11.2008, 14:44 | ||
вот пример, если классический полиморфизм не подходит и известны на стадии компиляции все используемые типы иерархии
|
Автор: Lycifer 7.11.2008, 17:13 | ||
![]() ![]() И как же будеш узновать где какой тип ? А не тоже самое с раздувжемся кодом ? А производительность?(не стоит забывать что С++ язык статичиский, визитор это пример более динамического обращения, мой пример можно без проблем перевести к стратегиям что еще ускорит скорость, и к рамеру exe не будет увеличен) ![]() |
Автор: Lazin 7.11.2008, 17:21 |
а твой switch не раздувание кода? ![]() |
Автор: J0ker 7.11.2008, 19:44 |
это, извиняюсь за мой французский, через жопу называется ![]() |
Автор: UnrealMan 8.11.2008, 17:56 | ||
Юзай http://www.boost.org/doc/libs/1_37_0/libs/ptr_container/doc/ptr_list.html |
Автор: Lycifer 11.11.2008, 11:33 | ||
- покажи что ты умееш - Умееш так , тогда делай вот это ..... - А так ты так не умееш тогда делай по другому .... Но в моём примере есть не достаток когда код растет(Добовляются новые классы удалять старые очень сложно особенно если это по коду разброссано, но это уже другой разговор) |
Автор: mes 11.11.2008, 14:31 | ||||||||
Ага все остается на совести программиста, и если он забыл посетить один из дальних уголков, то поведение системы непредсказуемо. Второй недостаток, что в каждой точке программы надо помнить что умеет делать каждый из объектов и как.
А чем хуже такое ? - а ну ка выполни это так, как умеешь. Но чтоб было хорошо! Основная прелесть ООП в том, что можно заставить объект самого решать поставленую задачу. Механизм виртуальных функций, помогает в этом, позволяя осуществить позднее связывание реализации с интерфейсом и при этом соблюсти все проверки типов на стадии компиляции. Классический полиморфизм используются для решния задач, когда кол-во выполняемых стабильно, в отличии от иерархии классов. Т.е мы знаем интерфейс но не знаем сколько и каких объектов будет. Двойная диспатчеризация (паттерн визитор) применяется в обратном случае, когда иерархия известна и стабильна, но интерфейс должен допускать легкое расширение функционала.
вот код показывающий имя типа, аналогично можно добавить числовый идентификатор, чтоб узнавать его и использовать в любой момент времени ![]() (основан на классах из предыдущего примера)
|
Автор: Lycifer 11.11.2008, 14:59 | ||||||
А если выполнить надо операции не имеющиго прямого связаности с классом? А тогда все просто мы просто зделаем прямую зависимоть нашего VISITOR от старонних действий!! 1)Локализация логики - чего? не она негодится мы же программисты серьёзные мы все зделаем в одном VISITOR'S(набит как самосат но работает......) 2)VISITOR'S он способен выполнить действия которые были у него внутри, то и есть что бы он что-то еще выполнил лезим во все классы, а что? Нам что не хочется перелопатить еще строк так это N стока? Да не , мы же программисты и постоянная отладка и печать текста нам по приколу...... 3)
4) Динамический полиморфизм стал классическим ![]() 5)
|
Автор: mes 11.11.2008, 15:27 | ||||
В вашем случае один Вызов виртуальной функции плюс свитч, что ставит скорости на один уровень.
Речь идет не о типе полиморфизма, динамическом или статическом, а о способе использования. Классический - линейный - выбор реализации функции зависит от типа объекта Двойная диспатчеризация - матричный - выбор основывается на типах двух объектов. Это применимо как к статическому полиморфизму, так и и к динамическому. Динамический же мы используем в нашем задании потому, что нам требуется хранить все наши типы в одном контейнере, и использовать элементы, зная базовый интерфейс. ООП отличается от процедурного не тем, что в первом используются классы, а тем логика выполнения задания объектом локализована. Приведенные функции в примере являются вспомогательными. И не "покушаются" внутренних особеностей объекта. |
Автор: Torsten 11.11.2008, 15:32 | ||||
Тока конечно еще лучше, как предложили юзать boost::ptr_list, т.к. он более удобен для работы с указателями и сам удаляем обьекты. |
Автор: mes 11.11.2008, 16:08 | ||||||||
а кто-то говорил , что надо запихивать все в один класс ? кесарю - кесарево ![]()
честно сказать мысль тут понял не до конца. Если речь о том что визитор должен реализовывать всю конкретную реализацию для каждого "посещаемого типа"объекта, то это не совершено не так. Визитор всего лишь switch. И нужен для того, 1. чтоб не было такого :
2. чтоб при изменении иерархии, компилятор бы визжал бы, а не позволял бы скомпилировать неправильный код, из за того что программист не удержал в памяти все места сравнения. 3. чтоб вызовы были определены и проверены на стадии компиляции, a не оставлялась возможность ошибки рантайма : ![]() |
Автор: J0ker 11.11.2008, 21:22 |
складывается впечатление, что Lycifer слышит звон, да не знает где он ![]() |