Как стать автором
Обновить

Комментарии 30

Становится так грустно, когда на С++ пишут бывшие паскалисты.

Внимание, вопрос. А зачем это может понадобится в реальном приложении?
Подобная вещь бывает нужна в реальном приложении (не в такой конечно реализации). Например в Qt широко используется метаобъект с пропертями, до которых можно достучаться по строковым именам (удобно например передавать такие строки как параметры методов или строить на них модульность (кстати именно за счет проперти построен дизайнер кутешный))
Мне кажется, но модульность куда удобнее строить на основе интерфейсов, а не слабосвязанной фигни.
Вам кажется.
Хорошо, давайте по-другому.

Я сам лично разработал модульное приложение на основе интерфейсов. А на основе слабосвязной фигни ни одного приложения не видел.
я вам привел в пример фреймворк Qt. Тот же дизайнер там построен на основе пропертей. Этого достаточно в качестве примера?
Реальный пример — есть вектор значений, построить на его основе карты (std::map) у которых ключами будут являтся разные поля методов (Имя и Идентификатор).
Подобная реализация позволяет сделать это двумя функциями (точнее двумя «инстансами» одной шаблонной). s-c.me/1jt
p.s. Я не паскалист.
Нет, я понял, как оно устроено, а для чего оно?
В частности для того, чтобы можно было не зная, с каким именно типом работаешь, а зная только какого типа поле и как оно называется получить его. Как-то так.
Тут интересная история получилась — пока этого механизма не было — не очень-то и надо было, а после его появления некое количество «фишек» стали не просто удобнее, а вообще возможны, к примеру — использование в стандартных алгоритмах (посредством функшиноидов).
Это из серии дождь->Идет() и рота_солдат->Идет() что ли?

Я имею ввиду не абстрактные варианты применения, а конкретное нечто. Например, если бы вы в качестве параметров использовали VARIANT, то можно было бы использовать его из скриптов собственного синтаксиса (например, вызов var.Field = 123 транслировался бы в m_mAllVariables[«var»]->SetField(«Field», CComVariant(«123»));) Однако, для этого лучше использовать IDispatch (в ATL в частности IDispatchImpl делает за вас всю работу, можно с помощью IDL специфицировать интерфейс, а потом сколько угодно работать с ним через GetIdsOfNames и Invoke).
Я и привёл конкретный пример.
Просто мой пример не содержит COM, IUnknown и прочей «неведомой фигни» (для меня неведомой, и не имею ни малейшего желания знакомиться с ней ближе).
Ой мама. Нахрена же статик то хранилище?
Да и общее впечатление не айс. Чего стоят только тайпдефы в начале и приведение к войду указателя на себя.
По порядку — статики — для того, чтобы писать одну функцию, а не делать шаблонный класс. А так получается по функции на тип, и по контейнеру на тип. С удалением правда не очень хорошо получилось, в том плане, что если явно не удалять — будут копиться «висячие указатели», но они удаляются, просто не очень красиво.
«Тайпдефы» просто для того чтобы не показывать, что в изначальном варианте там были UnicodeString (а вдруг кто-то захочет тоже поэкспериментировать?).
Приведение к войду указателя на себя — а что не нравится? Ну да, можно было бы явно хранить указатель на базовый класс, не спорю, было бы лучше (и как я это проглядел).
Я бы с радостью платил бы отчисления в фонд страхования программистов от необходимости писать на паскале, си, си++, пхп и прочей муре.
поздравляю — вы реализовали свой boost::serialize

Контейнеры удобны тем что ко всем их элементам можно применить одну операцию. И тут нам на помощь приходят виртуальные функции. Хранение же можно организовать так
std::map<MyBaseObject*>
или так
boost::ptrmap
без обид, рабочий код это хорошо — но у него пока много недостатков. Впрочем допускаю что в вашей программе вы храните и извлекаете много данных, и подобный базовый класс в разы упрощает работу с ними ( пример класс хранения конфигурации — хотя я для этого храню все в строках и при выводе преобразую налету в нужные типы ).
Тут не совсем сериализация — подавляющее число операций производятся непосредственно с полями. И только изредка посредством такой «неведомой фигни» — к примеру нужно сделать карту у которой ключом будет идентификатор — не вопрос, говорим мы и делаем шаблон в котором выбираем по ".Id", который есть почти у каждого нашего класса. А тут «внезапно» неплохо было бы сделать карту с ключём «ParentId», а для другого типа — по имени, и т.д.
В результате получается — есть объект заданного типа, мы его один раз «сериализуем», а после этого мы можем брать любые поля этого типа, путём присваивания и получения (думаю — стоит ли код писать или и так непонятно?).
А ещё есть возможность создать функциональный объект, указать ему применять такие-то функции к таким-то полям для сравнения, и использовать его для фильтрации.
А так, да — велосипедище. Но родное велосипедище. :)
родное это святое =)

но для моих нужд мне пока вышеупомянутых мэпов указателей обычно хватает. А если нехватает — тогда думаю специализированное под задачу решение.
const bigint INT_NULL = -1;

Доставляет.
Ну да. Такой вот NULL-тип, очень удобно отображать в базу данных и из неё, прозрачно проходит через границы раздела (веб-сервисы, сохранение в файл, загрузка из файла).
И всё же, уважаемый, что именно Вам доставляет эта запись?
Если кратко, то напоминает
#define true false
Если не кратко, то это не NULL-тип (да-да, это вам не SQL), а константа, которая своим названием полностью не соответсвует своему содержимому, чем доставляет много головной боли тем, кто будет поддерживать или развивать этот код.
Если же это попытка реализации тризначной логики, то отображение (область_значений(bibging) U INT_NULL) и область_значений(bibging) не взаимоднозначно (внезапно!), и имея значение -1 мы не можем определить является ли это значением -1, или же INT_NULL.
Поясню… INT_NULL в данном случае — произвольная константа, она запросто может быть и 0 — ничего от этого не изменится. Абсолютно. Потому, что это именованная константа. А создавать свой nullable тип только для того, чтобы можно было «идеалогически правильно» как-то ну совсем не верно. И используется для отображения NULL значений полей, которые в БД записаны как целые. В моей области применения вполне хватит 32-х бит, на первое время.
INT_NULL, на мой взгляд, достаточно говорящее название.
Может я не праильно понимаю, но что вы имеете ввиду под «отображения NULL значений полей, которые в БД записаны как целые»? Хотя это обсуждения уже явный оффтоп :)
RTTI это конечно прикольно, но многие вещи можно реализовать и иначе, да и нужно стараться это сделать RTTI никогда не добавляет резвости приложению. А в C++ к примеру есть шаблоны которые многое помогают решить, да на худой конец дефайны. А использование доступа по имени я считаю плохим проектированием.
Возможно вы не заметили, но тут как раз использование шаблонов и есть.
Забавно. Есть, правда, более красивый вариант на основе DIA SDK и PDB-файлов, описан здесь — msinilo.pl/blog/?p=517
использование RTTI и таких подходов — 90 процентов ошибка в проектировании.
пример с Qt и метаобъектов неверен, потому как он используется намного в более широком применении и использует совсем другие подходы.

Советую ознакопится с какой-нибудь документацией о проектировании приложений. Их хватает.
>>использование RTTI и таких подходов — 90 процентов ошибка в проектировании.
Использовать ORM?

>>пример с Qt и метаобъектов неверен, потому как он используется намного в более широком применении и использует совсем другие подходы
Интересная логика — этот пример не подходит, потому, что я знаю более узкий и с другим подходом…

>>Советую ознакопится с какой-нибудь документацией о проектировании приложений. Их хватает.
Пример такой документации?

Ещё раз — это решение конкретной, узкой задачи, которая описана в статье. Простое решение, простой задачи. «Большой» базовый класс, простые виртуальные функции (которые можно легко генерировать кодогенератором — к примеру CodeWorker'ом), простое использование, быстрое и без сторонних средств.
Мдааа… Как уже сказали выше, и как сказал большой гуру, то ли сам Страуструп, то ли Буч: «Если вам в С++ понадобилась информация о типе, значит вы неверно проектировали систему и вам стоит подучить С++».
Ужасный изврат.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории