![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() ![]() |
![]() |
ViGOur |
![]()
Сообщение
#1
|
![]() Мастер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: ![]() ![]() ![]() |
Я создаю динамически объекты некоторых произвольных классов, родитель у них один, тип только разный.
Для вопроизведения ошибки набросал следующий код:
В конструкции template <class T, int TYPE>, TYPE сделан для того, чтобы при инстанцировании различались типы объектов данного класса с задумкой на будущее... И данный тип передается динамически, во время выполнения программы. Тоесть, у меня из вне приходит некий tmpEnum, что в примере и я на основе него должен создать-получить объект mc4, но возникает ошибка указанная в коментарии при создании объекта mc4 . Как я понимаю это из-за того, что у меня переменная создается динамически (во время выполнения), а шаблон должен быть инстанцирован статически (во время компиляции). Поправьте меня если я ошибаюсь. И собственно вопрос, как сделать так, чтобы это работало и возможно ли это? ![]() Если это не возможно, то буду думать как сделать по другому... |
|
|
ssoft |
![]()
Сообщение
#2
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 130 Регистрация: 17.2.2010 Из: Москва Пользователь №: 1470 Спасибо сказали: 30 раз(а) Репутация: ![]() ![]() ![]() |
Как я понимаю это из-за того, что у меня переменная создается динамически (во время выполнения), а шаблон должен быть инстанцирован статически (во время компиляции). Поправьте меня если я ошибаюсь. И собственно вопрос, как сделать так, чтобы это работало и возможно ли это? ![]() Если это не возможно, то буду думать как сделать по другому... Имено так, шаблоны конкретизируются во время компиляции и нет возможности использовать динамически изменяющиеся параметры шаблона. В данном случае, я подозреваю, что необходимо использовать паттерн "Фабрика". |
|
|
ViGOur |
![]()
Сообщение
#3
|
![]() Мастер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: ![]() ![]() ![]() |
Боюсь паттерн Фабричный метод здесь не поможет, дело в том, что шаблонный класс реализован как синглтон, которому в качестве параметров передаются:
1. класс, объект которого нужно создать-получить. 2. некий внутренний тип, который явно идентифицирует объект, так как класс для некоего множества объектов может быть один, а тип у них разный... Например: Пока вижу только не очень хороший выход в использовании ручной типизации, но это геморно и чревато ошибками... ![]() Или я что-то не додумываю-недопонию? |
|
|
Iron Bug |
![]()
Сообщение
#4
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
если это связано с типами, то тожно тупо в конструкторе передавать std::type_info. ну или вообще что угодно.
|
|
|
ViGOur |
![]()
Сообщение
#5
|
![]() Мастер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: ![]() ![]() ![]() |
Неа, в моем случае объекты p3 и p4 (ePudel и eTaksa) это разные типы, и так как они по разному инстанцируются, то и разные объекты.
Простая передача параметра в конструкторе не даст того же результата... Например, p5 == p3, а p6 == p4, но p5 != p6.
|
|
|
Алексей1153 |
![]()
Сообщение
#6
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2944 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
имхо, виртуальное наследование спасёт )
|
|
|
ViGOur |
![]()
Сообщение
#7
|
![]() Мастер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: ![]() ![]() ![]() |
имхо, виртуальное наследование спасёт ) Это как я понимаю и есть фабричный метод! Боюсь паттерн Фабричный метод здесь не поможет, дело в том, что шаблонный класс реализован как синглтон, которому в качестве параметров передаются: И если это реализовывать, то в моем случае класс CPudel, будет заботится о создании самого себя, в место шаблонного класса (который, как я писал уже выше, является синглтоном), а вместе с этим в нем нужно будет закрывать: конструктор, деструктор, конструктор копирования и оператор присваивания... А так же, если в моем зоопарке будет за 100500 зверей, то всем им нужно будет делать то же самое и описывать своё рождение!Как-то не комильфо... Звери тут в качестве примера и не более! ![]() з.ы. или я все же не правильно понял идею вашей реализации. |
|
|
Алексей1153 |
![]()
Сообщение
#8
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2944 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
Это как я понимаю и есть фабричный метод! нет, это возможности языка. Фабрика - это отдельный класс/процедура, которая порождает объекты по маркеру их типа и возвращает указатель типа "родитель" синглтон можно сделать статическим методом родительского класса (синглтон Майерса) а описывать разницу в поведении типов всё равно где-то придётся ![]() можно все классы поместить в один namespace , тогда путаться ничего не будет |
|
|
ViGOur |
![]()
Сообщение
#9
|
![]() Мастер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: ![]() ![]() ![]() |
Пока я вижу выход, как я уже говорил:
Пока вижу только не очень хороший выход в использовании ручной типизации, но это геморно и чревато ошибками... в использовании switch, например так:![]()
|
|
|
Алексей1153 |
![]()
Сообщение
#10
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2944 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
ViGOur |
![]()
Сообщение
#11
|
![]() Мастер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
Алексей1153 |
![]()
Сообщение
#12
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2944 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
ViGOur, я - за инкапсуляцию )))
|
|
|
ViGOur |
![]()
Сообщение
#13
|
![]() Мастер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: ![]() ![]() ![]() |
да есть она там, но именно в данном случае она не нужна!
![]() |
|
|
Алексей1153 |
![]()
Сообщение
#14
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2944 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
it's enough of encapsulation! No more! ))
|
|
|
ViGOur |
![]()
Сообщение
#15
|
![]() Мастер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: ![]() ![]() ![]() |
ssoft, ты был прав, паттерн Фабричный метод самое то,единственное к нему понадобился плюс, в виде рекурсивного аргумента шаблона (это подсказал мне Flex_Ferrum) и все заработало!
Вот окончательный вариант с учетом моего примера:
Сообщение отредактировал ViGOur - 19.2.2013, 16:53
Причина редактирования: Поправил, был старый вставил старый тест...
|
|
|
ViGOur |
![]()
Сообщение
#16
|
![]() Мастер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: ![]() ![]() ![]() |
Изменил код, так как по невнимательности вставил код немного другого теста...
|
|
|
Алексей1153 |
![]()
Сообщение
#17
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2944 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
занимательно вышло, кстати, с точки зрения брейнфака )
с точки зрения практики- хм... Потом расскажешь ![]() Сообщение отредактировал Алексей1153 - 15.2.2013, 18:26 |
|
|
lanz |
![]()
Сообщение
#18
|
![]() Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
Какие подводные камни? |
|
|
ViGOur |
![]()
Сообщение
#19
|
![]() Мастер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: ![]() ![]() ![]() |
1. Данный код только для класса CAnimal и производных от него классов. ( я понимаю, что можно поправить, но все же!
![]() 2. При добавлении типа в CEnumClass::eEnum, тебе так же нужно будет добавлять прототип функции в массив creators. (если забыл добавить, то ... ) 3. Ты должен будешь соблюдать порядок типов в CEnumClass::eEnum и прототипов функций в массиве creators. (если порядок другой, то ...) |
|
|
lanz |
![]()
Сообщение
#20
|
![]() Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
Все верно, но это из-за ограничения на то что должно быть соответствие между классами и enum.
Если его снять, то получится либо rtti, либо чистые шаблоны. Чего то я не очень догоняю зачем их смешивать. Как я понял, задача состоит в том чтобы сделать N различных типов. А зачем? Все равно они будут использоваться через один и тот же интерфейс (CAnimal*). А если это для того чтобы сделать статическую проверку типов, то все равно ничего не выйдет (та же проблема что и в первом посте). Можно какой нибудь пример использования? |
|
|
ViGOur |
![]()
Сообщение
#21
|
![]() Мастер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: ![]() ![]() ![]() |
Можно какой нибудь пример использования? Легко, правда это не мой пример, долго объяснять, потому не буду, дам пример по проще, но суть будет примерно та же...Пишется модуль по работе с протоколами, пускай они будут подключаться как плагины. На данный момент мы должны уметь подключать к нему такие протоколы как HTTP и FTP. А если понадобиться позднее подключать SNMP. А еще позже SMTP, POP3, IMAP. А в конце концов скажут подключаем прикрутит еще чего, как ты будет закладываться на все это? |
|
|
lanz |
![]()
Сообщение
#22
|
![]() Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
Можно так, с учетом пунктов 1, 3.
Вместо енума можно использовать текстовые идентификаторы например(или генерить на лету). Тогда и пт. 2 сильно не влияет. В загрузку плагина не забудешь запихнуть регистрацию класса(а если и забудешь, легко ловится тестами). А еще без перекомпиляции при изменении enuma ![]() Раскрывающийся текст
|
|
|
ViGOur |
![]()
Сообщение
#23
|
![]() Мастер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: ![]() ![]() ![]() |
Честно говоря, ИМХО особо ничего не поменялось...
![]() Мне вот вспомнилась задачка от яндекса, при тестировании знаний перед собеседованием: Есть класс CodeGenerator, который умеет генерить код на разных языках.
Исходя из предположения, что количество языков будет увеличиваться, предложите refactoring кода. Аргументируйте преимущество вашего кода над существующим. ( Оригинал ) |
|
|
lanz |
![]()
Сообщение
#24
|
![]() Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
Цитата 1. Данный код только для класса CAnimal и производных от него классов. ( я понимаю, что можно поправить, но все же! ) Теперь шаблон. Цитата 2. При добавлении типа в CEnumClass::eEnum, тебе так же нужно будет добавлять прототип функции в массив creators. (если забыл добавить, то ... ) Вместо этого регистрация (=1 действие), но тут никуда не дется, если берем за референс реализацию с рекурсивными шаблонами, то там придется добавлять enum + делать полную специализацию CClass (=2 действия) Два действия забыть проще .) Цитата 3. Ты должен будешь соблюдать порядок типов в CEnumClass::eEnum и прототипов функций в массиве creators. (если порядок другой, то ...) При регистрации порядок неважен. В задаче от яндекса то же, только в профиль. Немного интересней, что зависимые от языка вещи находятся в двух местах, но это непринципиально, сюда тоже можно сунуть фабрику. Плюсы - только уменьшеие количества мест, которые нужно исправить при переделке и как следствие повышение багоустойчивости. Минусы - усложненная архитектура. Вообще switch неплох, когда у нас участвует менее 6-7 элементов. Поэтому при прочих равных, я бы максимум убрал второй switch. Как то так. Раскрывающийся текст
|
|
|
Iron Bug |
![]()
Сообщение
#25
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
знаешь, я вообще перечитала твою тему с начала и подумала, что я тут уже писала на этот счёт. только у меня задача сложнее была, с библиотеками, но смысл был совершенно тот же.
у меня была задача сделать плагины к существующему коду так, чтобы плагины было можно подцеплять отдельно, динамически, не трогая весь остальной код. и чтобы они наследовали общее поведение в некоторых методах. http://www.forum.crossplatform.ru/index.php?showtopic=6472 |
|
|
ViGOur |
![]()
Сообщение
#26
|
![]() Мастер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: ![]() ![]() ![]() |
Да я уже сдела что хотел и вылодил описание как...
Просто lanz, предлагает свое решение, которое мне явно не подходит. ![]() |
|
|
lanz |
![]()
Сообщение
#27
|
![]() Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
Почему, ну почему-же не подходит?!
![]() |
|
|
ViGOur |
![]()
Сообщение
#28
|
![]() Мастер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: ![]() ![]() ![]() |
Почему, ну почему-же не подходит?! А вот почему:![]() "Код"
1. добавить его в enum Lang перед LANG_END. 2. добавить специализацию шаблона langCodeGenerator для него: И не более того! ![]() |
|
|
lanz |
![]()
Сообщение
#29
|
![]() Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
Ну да, но если сравнивать:
Раскрывающийся текст
Минусы - оверхед на регистрацию + оверхед на хранение, если забыть зарегистрировать - ничего не заработает (будет ошибка времени выполнения, а не времени компиляции), слишком усложненное использование для небольшого числа объектов. Плюсы - читается лучше(при всей моей любви к шаблонам, рекурсивные шаблоны - это "особая шаблонная магия"), не надо перекомпилировать все классы языков при добавлении нового (это кстати позволит разнести их по дллкам например и загружать динамически), в вашем решении каждый вызов instance будет рекурсивным и пробегатся по всей иерархии шаблонов (т.е. получится тот же switch, только "размазанный по коду". |
|
|
ViGOur |
![]()
Сообщение
#30
|
![]() Мастер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: ![]() ![]() ![]() |
Со всем в принципе согласен, но как я уже говорил под мои нужды это самое то!
У меня уже за 20 разных объектов в enum'е и думается мне их прибавится! И если что-то не так, то лучше узнать об этом на этапе компиляции... ![]() |
|
|
lanz |
![]()
Сообщение
#31
|
![]() Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
Конечно надо использовать то что лучше подходит, каждый случай уникален!
![]() Просто мне и самому хотелось поподробнее плюсы и минусы разобрать, а то этот метод уже в идиому для меня превратился. Ну и кроме того теперь буду использовать шаблонный class_creator и фабрику вместо того чтобы для каждого нового класса писать свой ![]() Спасибо за содержательный диалог! |
|
|
![]() ![]() ![]() |
![]() |
|
Текстовая версия | Сейчас: 16.7.2025, 17:48 |