![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Пытаюсь сделать "правильный" дизайн приложения. Есть классы типа Settings, DownloadManager, ScriptManager, JobManager.
И 3 класса должны иметь доступ к Settings, чтобы читать и писать свои данные. Напрашивается синглтон, но мы знаем, что это антипаттерн и поэтому он быстро "распрашивается" обратно. Альтернатива - передача указателя на Settings в конструктор каждого объекта (или через метод setSettings, что менее рекомендуемо). По сути советуют использовать Dependency Injection / Inversion Of Control (IoC) (пока разницы не понял, говорят, что одно частный случай другого). Сам паттерн не ограничивается передачей указателя на экземпляр класса, это должен быть указатель на интерфейс для конкретного класса типа ISettings, чтобы жестко не привязывать объекты друг к другу (забыл как называется это принцип ООП). Собственно на этой стадии реализация паттерна не идеальна (уже не помню почему), поэтому предлагают использовать так называемый контейнер (DI Container). Это разновидность шаблона Service Locator'а, где регистрируется связка КлассИнтерфейса=КонкретныйКласс. Обычно эти контейнеры настолько наворочены, что их выделяют в отдельные фреймворки и библиотеки. Собственно это то к чему я пришел убегая от сиглтона. Почему в рунете так мало информации о паттерне Dependency Injection? А в англоязычных ресурсах информация представлена на 90% с примерами на Java. Я понимаю, что шаблон придумали именно разработчики Java, но неужели проблемы не существует на C++, что почти не реально найти примеры и классы? Что используете в разработке вместо Одиночек? |
|||
|
||||
boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
я бы предпочел синглтон. хоть это и антипаттерн, но иногда без него никуда.
второй вариант - передавать ссылку на Settings. чтоб не привязываться к типу, тип ссылки можно передать как шаблонный тип. ну или интерфейс(как вы и писали). Это сообщение отредактировал(а) boostcoder - 12.8.2010, 22:55 |
|||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Передаю, грубо говоря, shared_ptr< [const] Settings > в конструктор. Собственно, не очень понял, что такое Dependency Injection и чем оно лучше даже того же синглтона.
|
|||
|
||||
djamshud |
|
|||
![]() Пердупержденный ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 23.11.2009 Репутация: 8 Всего: 39 |
Предложу анти в кубе не-паттерн: глобальный объект сеттингс. У вас (не теоретически, а практически!) может быть одновременно несколько наборов настроек, параллельно живущих и использующихся во время работы программы? Нет? Тогда плюньте на теоретика Александреску и решайте свою задачу, а не высосанную из пальца проблему.
Добавлено через 37 секунд Впрочем и синглтон в равной степени подходит... -------------------- 'Cuz I never walk away from what I know is right Alice Cooper - Freedom |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Лучше тем, что не singleton с его недостатками. В принципе не сложно писать такие цепочки:
Другое дело, что вариант не идеален, а как работают DI Container'ы для C++ я пока не до конца разобрался. |
|||
|
||||
Любитель |
|
|||
Программист-романтик ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3645 Регистрация: 21.5.2005 Где: Воронеж Репутация: 24 Всего: 92 |
Во-первых, с иок-ом, как таковым, всё просто - не делай зависимости класса A от класса Settings. Делай интерфейс ISettings и работай с ним.
Но, во-вторых, это неудобно - т. к. придётся передавать указатель на объект настроек. "Инъекция" возможна только в том случае, если все объекты мы получаем через DI-контейнер. Т. е. в итоге мы: 1. Регистрируем (где-нить при старте приложения) маппинг: ISettings -> DbSettings, или XmlSettings, или IniSettings (да, вообще логично что Settings - это чисто объект данных, а методы load/save/etc. в SettingsManager-е каком-нибудь, ну да ладно). 2. Добавляем параметр типа ISettings в конструктор нашего класса A (инъекция в конструктор - самая простейшая и достаточно популярная). 3. Вместо создания объекта класса A пишем container.Resolve<A>(). В общем-то всё красиво. У DbSettings у нас будет IDbConnection (я условно), который тоже автоматом зарезольвится на что надо - и т. д. Более того, любой DI-контейнер на практике действительно является и сервис локатором ("чистый" DI-контейнер должен производить только "инъекции", а создание/получение объектов - не его дело, но на практике такого не бывает). А это значит, что мы также можем регулировать время жизни объектов и пр. Теперь проблемы. Любой настоящий DI-контейнер реализуется с использованием рефлекшена. Именно поэтому это (в основном) ява/шарп. В чистом С++ "правильного" DI вообще не может быть. С учёток оберток, предоставляющих метаданные (как в том ж Qt) - в принципе сделать вомзожно, но я не встречал готовых реализаций. В случае С++ на мой взгляд есть 2 варианта: 1. Если нужна действительна абстракция - простейшая фабрика, без каких либо наворотов. 2. Если нет - то синглтон ![]() Более того - даже в случае явы/шарпа я бы не стал городить иерархии классов/интерфейсов и полную абстракцию, если это бы действительно не было бы нужно. |
|||
|
||||
SABROG |
|
||||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Они есть: QNimbleContainer QtIocContainer Другое дело, что они жестко привязаны к мета-объектной системе и как следствие любой класс должен наследовать QObject. К тому же не хотелось бы использовать сторонние библиотеки/фреймворки ради того, чтобы просто уйти от синглтона.
То есть реализовать Service Locator через фабрику и передавать указатель на IServiceLocator через конструктор в каждый объект, типа этого? Эхх, если начать реализацию синглтона, то помимо идеологических проблем существует и физиологическая - проблема с потоко-безопасностью. Чтобы его сделать потоко-безопасным придется прибегнуть к double checked locking паттерну реализованному через атомарные операции, которых пока нет в C++, это значит надо использовать сторонние библиотеки, BOOST например (ну или начать использовать функции из C++0x) |
||||
|
|||||
Любитель |
|
||||||
Программист-романтик ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3645 Регистрация: 21.5.2005 Где: Воронеж Репутация: 24 Всего: 92 |
Совсем не впечатлило. Всё делать через плагины - это жёстко. Здесь уже гораздо лучше. Беглый просмотр блога говорит о том, что направление выбрано верное. Но.. насколько это production ready - уже другой вопрос (всё-таки пока похоже больше на грамотное увлечение).
Ну.. так или иначе они будут расчитывать на некоторый базовый класс - для эмуляции рефлекшена (черех собственное хранилище метаданных). Ну или точнее так - в принципе базовый класс не обязательно, но на хранилище метаданных обязательно (ну плюс там ещё проблема универсальной передачи параметров появляется, решаемая в Qt через QVariant).
Ну.. Service Locator реально нужен когда? Когда у нас накапливается много объектов, создаваемых через фабрики. И особенно, если при этом между ними есть какие-то связи. Т. е. по сути это централизованная фабрика. Т. е. в простых случаях достаточно обычных фабрик (per class). Далее - передавать указатель на IServiceLocator я бы не стал. Уж саму фабрику точно делал бы синглтоном, ну или просто статик поля/методы. Смысл абстрагировать абстракцию?
Во-первых, в плане life scope в случае навороченных DI-контейнеров всегда есть опция синглетона. Наличие одного (и только одного) экземпляра класса в системе - не есть плохо. Плохо то, что мы жёстко зависимы от этого. Во-вторых - будут ли проблемы с потоками, это зависит от конкретного кода объекта. И в большинстве случаев наиболее удачным решением будет просто использование TLS а не локи (по крайней мере уровень паралелизма будет гораздо выше). Любой уважающий себя компилятор это поддерживает, одним дефайном решается необходимость привязки к конкретному компилеру. |
||||||
|
|||||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 53 Всего: 183 |
TLS - это хороший выход только если каждый поток должен иметь свой экземпляр. А это вроде бы не так. Если система не очень сложная, может, не стоит парится с thread-safe синглетона. Т.е. доступ к данным действительно нужно синхронизировать. А "double checked locking паттерн" реально нужен только, если возможны накладки при создании или уничтожении. -------------------- ... |
|||
|
||||
Леопольд |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Это сообщение отредактировал(а) Леопольд - 13.8.2010, 10:20 -------------------- вопросов больше чем ответов |
|||
|
||||
Леопольд |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
-------------------- вопросов больше чем ответов |
|||
|
||||
Леопольд |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Не пойму, зачем здесь атомарные операции? Любой поток будет залочен до тех пор, пока объект не будет полностью сконструирован. Это сообщение отредактировал(а) Леопольд - 13.8.2010, 11:34 -------------------- вопросов больше чем ответов |
||||
|
|||||
SABROG |
|
||||||||||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
QtCreator для кода:
Использует разновидность синглтона Мейерса. Только если в оригинале он не потоко-безопасен, то у них подход хитрее. Предполагается, что любое приложение изначально создается как single threaded, поэтому пока мы не наплодили других потоков предварительно происходит инициализация всех "синглтонов", например где-нибудь в main(). Сам вариант приблизительно выглядит так:
Недостатки такого подхода очевидны, но я пока склоняюсь к этому варианту, как наиболее простому и хоть частично потоко-безопасном по сравнению с таким вариантом, который без синхронизации потоков вообще не безопасен:
Чтобы отвязаться от класса ServiceLocator, впихнуть тесты, при желании подсунуть "заглушку". Предположим я хочу научиться делать автомобили. Специалисты отправляют меня сначала научиться делать велосипеды. Когда я научусь их делать, то настанет очередь чего-то более сложного. То есть на данном этапе мне важно не быстрей что-либо написать, а понять как делать это правильно в будущем, когда такая необходимость настанет.
В случае заранее проинициализированного указателя проблем атомарного чтения самого указателя возникнуть не должно (по крайней мере на AI-32), а работу с данными на которые он указывает нужно синхронизировать, благо в Qt достаточно поток-безопасных классов и Qt сама берет на себя эту рутину. Тут конечно остается проблема с "висячим" объектом синглтона, который может быть даже и не используется нигде в коде (но это редкий случай, нафига его тогда вообще создавать).
Во первых мутекс блокирует работу всех остальных потоков, которые пытаются получить доступ к синглтону, а могли бы делать полезную работу. Если дальше копать, то там нужен второй мутекс, а потом в итоге и он не спасает, погугли на "Double Checked Locking Broken". Как я уже упомянул нужен "безопасный" вариант шаблона Double Checked Locking, который реализован в функции boost::callonce(), вот пример нормального потоко-безопасного синглтона: http://www.boostcookbook.com/Recipe:/1235044 Но это мне не подходит, так как я пока не хочу тянуть boost, да еще и ради антипаттерна. Это сообщение отредактировал(а) SABROG - 13.8.2010, 11:49 |
||||||||||
|
|||||||||||
Любитель |
|
||||
Программист-романтик ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3645 Регистрация: 21.5.2005 Где: Воронеж Репутация: 24 Всего: 92 |
А, так ты ведёшь речь именно про создание инстанса. А я то думал про "небезпоасные" его методы. Если ты уверен в безопасности методов - то очевидно, что тут и обычные объекты синхронизации (т. е. обычная блокировка) подойдут:
Ну.. А создание сервис локатора кто-то ж будет делать? Потом будем это создание абстрагировать и т. д. Я не очень вижу в этом смысл. Заглушку на классы, занимающиеся "функционалом" - ок. Тесты - ок. Но зачем сервис-локатор абстрагировать? Единственный случай, который можно придумать - это желание использовать для него какой-т фреймворк и возможность переключение между разными фреймворками (не в процессе, а в перспективе проекта). Но.. это только если речь про достаточно нетривиальную реализацию. |
||||
|
|||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Так это и есть тот самый "сломанный" вариант Double Checked Locking паттерна. Зачем-то разработчики Microsoft его используют (IServiceLocator + IServiceProvider). Видимо, чтобы конечный пользователь мог подставлять собственные фабрики. К тому же опять идет жесткая привязка к конкретной реализации: ![]() |
|||
|
||||
Леопольд |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Блокирует только если инстанс не создан и до тех пор, пока он не будет создан целиком, иначе просто возвращает указатель без блокировки. -------------------- вопросов больше чем ответов |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
||||
|
||||
Леопольд |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Это сообщение отредактировал(а) Леопольд - 13.8.2010, 13:24 -------------------- вопросов больше чем ответов |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Это относится к одному потоку. Каждый поток будет создавать целиком по своей копии. На уровне компилятора тут нет синхронизации. Не забывай и про такую ситуацию:
|
|||
|
||||
boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
ради call_once() boost тащить не надо. она есть во всех свежих версиях компиляторов. Добавлено через 1 минуту и 56 секунд SABROG, мешанина какая-то в теме.. в данный момент, как я понял, проблема в инициализации синглтона? или в чем? Добавлено через 2 минуты и 40 секунд по моему, она есть даже в Qt. |
|||
|
||||
SABROG |
|
||||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Она есть только в стандарте C++0x. Я конечно не консерватор, но стандарт еще не принят и хочется переносимости на старые компиляторы.
Сейчас мне интересно мнение насчет варианта без синглтона, варианта, который используется в нескольких проектах, которые я обнаружил через google/codesearch. То есть разновидность глобальных указателей:
Нету, я писал свою реализацию при помощи Дмитрия Вьюкова (специалиста по конкурентному программированию). |
||||
|
|||||
Леопольд |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Спасибо. Упустил этот момент. Добавлено @ 14:12 Хорошо сочетается с принципом KISS ![]() Это сообщение отредактировал(а) Леопольд - 13.8.2010, 14:13 -------------------- вопросов больше чем ответов |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
||||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Вопрос задавался в контексте языка C++, а не конкретного фреймворка. А так то варианты есть. |
|||
|
||||
Леопольд |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
![]() Это сообщение отредактировал(а) Леопольд - 13.8.2010, 16:34 -------------------- вопросов больше чем ответов |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
1. суть не меняется... настройки это часть приложения, через него они и должны быть доступны.. 2. синглетон не всегда антипаттерн. Антипаттерн - применять синглетон без обдумывания. дальнейшее зависит от задачи и фреймворка. |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
К сожалению не спасет от двух видов оптимизации. Одну делает компилятор, другую может делать линкер. Как получить гарантии того, что этих оптимизаций производиться не будет на всех известных компиляторах? Как сказали бы Александреску с Мейерсом: "Game over. You lose." Почитай статью, чтобы не придумывать новых велосипедов. |
|||
|
||||
Леопольд |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
volatile указатель на функцию, и вызов функции через этот указатель. Александреску конечно умный мужик, но это не повод унывать... ![]()
Если есть какие-то сомнения, то можно заменить на виртуальный вызов через указатель на базовый класс. Наследника определить в другой единице трансляции, на всякий случай. Это сообщение отредактировал(а) Леопольд - 13.8.2010, 18:50 -------------------- вопросов больше чем ответов |
|||
|
||||
Леопольд |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Читал, где-то год назад. Вот ещё интересная статься под авторством Александреску. http://www.drdobbs.com/184403766;jsessioni...HPSKH4ATMY32JVN
-------------------- вопросов больше чем ответов |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Следом идет другая проблема - когерентность кеша. У каждого ядра/процессора своя копия данных памяти в кеше и когда один поток меняет данные (устанавливает указатель, инициализирует члены класса), то нужно об этом сообщать другим потокам, иначе у них останутся "старые" данные. То есть возникает необходимость добавлять барьеры памяти или использовать атомарные инструкции типа Acquire/Release, чтобы сообщать другим потокам, что чего-то изменилось и кеши нужно обновить. Стандартных механизмов сделать это в C++ нет. На данном этапе этот язык совершенно не подготовлен к конкурентному программированию. К счатью работа в этом направлении ведется и с новым стандартом мы получим полноценный набор атомарных методов.
|
|||
|
||||
Леопольд |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
-------------------- вопросов больше чем ответов |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
||||
|
||||
boostcoder |
|
||||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
SABROG, ваша ситуация ясна.
но последующими вопросами, вы, похоже, пытаетесь всех загрузить? ![]() то, о чем вы мыслите - правильно. я бы сказал, через чур правильно. т.к. сложность на реализацию "правильного", переплевывает все адекватные времячасовые расходы. в с++0х есть способы борьбы. угу.
угу. смотрите Go
угу. а вы только краски сгущаете. не забывайте о том, в каких годах, и для какого оборудования разрабатывался с++. Это сообщение отредактировал(а) boostcoder - 14.8.2010, 00:27 |
||||
|
|||||
SABROG |
|
||||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Нет, просто объяснил свою позицию насчет синглтонов. Думаете мне хотелось вдаваться в детали проблемы? Это всего лишь ответы на ваши вопросы.
Я думаю это тот случай, когда достаточно один раз сделать правильно и использовать в последующих проектах. То, что в итоге можно сделать потоко-безопасный синглтон не устраняет его проблемы как антипаттерна. Да, можно применять его ограниченно, обдуманно, но вот еще бы знать где эти границы и есть ли они у других разработчиков, которые будут дописывать код.
Самое смешное в том, что за последние 20 лет вышло такое количество разных языков программирования, где многих недостатков C++ просто нет. Когда у меня на компьютере по нескольку раз в неделю обновляется виртуальная машина Java я вижу насколько быстро этот язык развивается. Я не вижну какой-то активности по этому поводу со стороны разработчиков C++. А они вообще есть? Есть люди, которые пишут инструкцию (стандарт), а есть те, кто на основе неё пишет компилятор (ms, gcc, intel), и каждый делает это по своему разумению, да так, что производительность, устойчивость, переносимость программ с одним и тем же исходным кодом - разная. |
||||
|
|||||
Леопольд |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
![]() Это сообщение отредактировал(а) Леопольд - 14.8.2010, 09:08 -------------------- вопросов больше чем ответов |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Почитал, что предложил JackYF, вроде тоже вариант не плохой. Как насчет такой реализации?
Конечно банальная передача указателя через конструктор, в дальнейшем пойдет через метод settings() по цепочке во внутренние объекты. Плюсы в том, что умный указатель следит за жизнью объекта, его валидность почти всегда можно проверить. Класс ISettings позволяет разбить зависимость между двумя классами таким образом, что классы можно будет тестировать по отдельности не говоря о том, что можно подсовывать разные реализации этих настроек, например если они отличаются методом хранения (файл, база данных, сеть). Это сообщение отредактировал(а) SABROG - 14.8.2010, 14:47 |
|||
|
||||
boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
ИМХО, операторы new в main() лишние. и смартпоинтер в этом случае не нужен.
|
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Как бы предполагается, что эта реализация может работать не только в main(), но и в каком нибудь MainWindow. Без new смарт поинтеры вроде как работать не могут. Все-таки удалять в деструкторе локальную переменную через delete - чревато. |
|||
|
||||
boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
смешно. я лишь хотел сказать, что невижу необходимости, создавать эти объекты при помощи new. они легко могут быть автоматическими переменными, даже членами класса. Это сообщение отредактировал(а) boostcoder - 14.8.2010, 15:25 |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Ситуации разные бывают, иногда необходимо освободить ресурс, если он никому не нужен. В случае с объектами созданными в main() этого освобождения не будет (как в коде, который я написал). Но если время жизни объекта, который проинициализировал другой объект, который должен жить пока нужен кому-то, меньше, то нет смысла занимать память двумя объектами сразу только потому, что объект является хозяином указателя/ссылки. |
|||
|
||||
boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
да. но вашим кодом, вы обязываете пользователя использовать new. |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
||||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
В общем как обычно, с этими интерфейсами больше проблем.
Далее в коде нужно передавать указатель типа QObject во внутренние классы Qt. И тут возникает проблема downcast'инга от класса интерфейса да DownloadManager'a. В общем каждая собачка - зверушка, но не каждая зверушка - собачка. Наследовать интерфейсы от QObject'a тоже как-то не хочется, как-то это не легковесно. |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
все зависит от того, что должен выражать интерфейс.. |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Да я и сам не знаю ![]() |
|||
|
||||
Леопольд |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
SABROG, не пойму, чем это лучше обычного синглтона... К тому же, если скорость критична (не просто так ведь заботишься о расходах на синхронизацию кэша ядер?), то виртуальные вызовы не лучший вариант.
Если не обойтись без downcasting'а, но dynamic_cast недопустим (в релизе), то можно использовать checked_cast... Я его выдернул из книги Александреску и Саттера "Стандарты программирования на С++" Хотя, IMHO лучше всё же обойтись... Это сообщение отредактировал(а) Леопольд - 17.8.2010, 10:45 -------------------- вопросов больше чем ответов |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
А разве есть какой-нибудь оверхед, если метод интерфейса чисто виртуальный?
|
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
от чистоты ничего не зависит. виртуальный вызов более дорогостоящ, чем _прямой_. и еще не понял, какая связь между синглетоном и Dependency Injection в рамках этой темы ? одно не альтернатива другому, а дополнение. Это сообщение отредактировал(а) mes - 17.8.2010, 18:20 |
|||
|
||||
SABROG |
|
||||||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Разве? Разница такая вроде бы: // Dependency Injection
// Singleton
|
||||||
|
|||||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |