![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
georain |
|
||||||||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 193 Регистрация: 28.11.2006 Где: Санкт-Петербург Репутация: нет Всего: нет |
Вот приходят из сети данные блоками, в начале блока есть число - идентификационный номер класса который он содержит. Нужно преобразовать блок в класс с помощью статической функции этого класса.
Пользоваться case не хочу, классов много, хочу чтобы работало быстро ![]() Вот мой вариант: У меня дерево классов полиморфное. В каждом классе делаю статическую функцию которая принимает указатель на данные, возвращает указатель на базовый класс указывающий на новый класс (производный с нужным номером) созданный из этих данных. Это удобно потому что методы инкапсулированны внутри классов.
Делаю enum - перечисляю все мои классы, номера для каждого класса беру из протокола
Далее делаю финт ушами
Для создания нужного класса пишу
В итоге вместо множественного case получаю быстрый вызов нужной функции. Реализация мне нравится, но может есть что получше? Потому что во-первых велосипед наверняка, а во вторых надо не забыть каждый класс в таблицу записать и в enum ещё. Это сообщение отредактировал(а) georain - 15.2.2008, 15:23 |
||||||||
|
|||||||||
marcusmae |
|
|||
![]() stravaganza ![]() ![]() Профиль Группа: Участник Сообщений: 874 Регистрация: 26.3.2006 Репутация: 5 Всего: 39 |
georain, действительно, велосипед солидный. Задача, как я понял, из потока распознать и десериализовать объекты. Если у вас дерево классов полиморфное, то почему нельзя эту иерархию как-то удобнее закодировать, чем прямой нумерацией? От этого в итоге будет зависеть, на сколько быстро их будет распознать.
-------------------- ἀπὸ μηχανῆς θεός |
|||
|
||||
Alek86 |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1299 Регистрация: 30.1.2007 Где: Киев Репутация: 21 Всего: 25 |
удалил
Это сообщение отредактировал(а) Alek86 - 15.2.2008, 15:56 |
|||
|
||||
georain |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 193 Регистрация: 28.11.2006 Где: Санкт-Петербург Репутация: нет Всего: нет |
Ну так я и прошу совета, подскажите какой есть способ лучше. На счёт нумерации классов, а как можно удобнее закодировать, чем это будет лучше и чем плохо прямой нумерацией? |
|||
|
||||
Alek86 |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1299 Регистрация: 30.1.2007 Где: Киев Репутация: 21 Всего: 25 |
думаю, тут можно так извратиться
раскоментируй все строки и, вникая, увидишь, что при отсутсвии или номера или связи между номером и типом будет бабах (причем, в общем, читабельный) ![]() Добавлено @ 16:49 а способа лучше я не смог придумать (применимо к передаче кода класса вначале). Это сообщение отредактировал(а) Alek86 - 15.2.2008, 16:50 |
|||
|
||||
Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 41 Всего: 154 |
Думаю наиболее стандартным решением будет использование указателей на производящие ф-ии
потом когда приходит пакет можно очень быстро найти нужную ф-ю, скорость конечно ниже чем у switch, зато эта реализация масштабируется |
|||
|
||||
Mayk |
|
||||
![]() ^аВаТаР^ сообщение>> ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 2616 Регистрация: 22.5.2005 Где: за границей разум а Репутация: 45 Всего: 134 |
В принципе вместо map'а можно использовать hash_map или даже vector. Ну а фабрику можно инициализировать статически
-------------------- Здесь был кролик. Но его убили. Человеки < кроликов, йа считаю. |
||||
|
|||||
marcusmae |
|
|||
![]() stravaganza ![]() ![]() Профиль Группа: Участник Сообщений: 874 Регистрация: 26.3.2006 Репутация: 5 Всего: 39 |
georain, я бы посмотрел, например, следующее : пусть есть всем базовый класс А, его наследники A1, A2, у каждого их которых по паре своих - A11, A12 и A21, A22 соотвественно. Кодировать - цепочку наследования, скажем, для A22 : просто "A-A2-A22" или, нумируя наследников, "00-01-01" - битами, байтами, символами - как-угодно. Ещё пример для A12 : "00-00-01" и т.п. Что за цепочки получились? = Это - пути в дереве наследования. Таким образом, проблема поиска типа сведена к задаче поиска в дереве. Оно, конечно, имеет свои ньюансы, скажем, в отличие от case по прямой нумерации, по ходу поиска отсекается большое число вариантов.
georain, можно много-чего посоветовать, способов много, тк проблема весьма абстрактная. А принятие ответственности за выбор способа решения для Вашего конкретного бизнеса - одна из составляющих работы ![]() -------------------- ἀπὸ μηχανῆς θεός |
|||
|
||||
Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 41 Всего: 154 |
а так более кошерно))
Это сообщение отредактировал(а) Lazin - 16.2.2008, 13:28 |
|||
|
||||
Alek86 |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1299 Регистрация: 30.1.2007 Где: Киев Репутация: 21 Всего: 25 |
marcusmae, раз говоришь, что есть много способов создания классов по данным из потока, то не мог бы ты сказать, как это сделать лучше для N классов, не связанных родственными узами? ну, или ссылку, как обычно
![]() потому как мне задачка понравилась, но ничего лучше представленного в пером посте (ну, + некоторые мета-уловки, которые, возможно, упростят жизнь при добавлении новых классов) не придумал |
|||
|
||||
marcusmae |
|
|||
![]() stravaganza ![]() ![]() Профиль Группа: Участник Сообщений: 874 Регистрация: 26.3.2006 Репутация: 5 Всего: 39 |
хорошо сказал ![]() вообще-то с самого начала речь шла о полиморфном дереве классов, ну а если нет, то его всегда можно искусственно создать, определив, к примеру, базовый абстрактный класс :
Уже после того, как вчера появились последние посты, я подумал, а как вообще нужно докатиться (в негативном смысле) до ситуации, когда в потоке непонятно-какие объекты, типы которых подлежат определению? Вижу две возможности : 1) на машине в сети работает программа с функцией main(), в которой наинициализирована и сериализована целая армия экземпляров разных типов. Но вообще-то так в кучу обычно не сваливают, а создают большой класс-контейнер Main или, как в .NET, Program, для которого уже можно определить функцию сериализации (которая в т.ч. будет вызывать сериализацию составных компонентов) и отправлять в поток уже как целостный объект. 2) экземпляр класса не может сериализовать сам себя. Если он сериализовался, то что-то извне этого потребовало : явный вызов или исключение. Это можно было бы обыграть, чтобы как-то дополнительно облегчить работу серверу. -------------------- ἀπὸ μηχανῆς θεός |
|||
|
||||
Alek86 |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1299 Регистрация: 30.1.2007 Где: Киев Репутация: 21 Всего: 25 |
ну "вот так вот получилось"
причем я легко могу представить, чтобы мне пришел некий отсериализированный контейнер разнородных данных. да пусть и однородных. Как их в этом случае рассовывать по классам? я вижу только вариант с ID |
|||
|
||||
marcusmae |
|
|||
![]() stravaganza ![]() ![]() Профиль Группа: Участник Сообщений: 874 Регистрация: 26.3.2006 Репутация: 5 Всего: 39 |
Alek86, получиться может много-чего, просто улучшаемость заведомо плохих решений весьма ограничена. Ты сказал ключевое слово контейнер. Раз он есть, значит 1) его тип известен - можно сразу вызывать его десериализатор 2) "рассовывать" - забота контейнера, он должен уметь своим методом Deserialize прочитать, что в нём лежит. Этот вариант я описал в (1). А не нравится мне вариант, когда контейнера нет. То есть, просто ткнули заголовок и указатель на байты и длину - то, о чём шла речь вначале. Вот мне интересно : зачем тот, кто это сделал, так сделал? Это сообщение отредактировал(а) marcusmae - 16.2.2008, 17:18 -------------------- ἀπὸ μηχανῆς θεός |
|||
|
||||
tol05 |
|
||||||||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1632 Регистрация: 21.12.2006 Где: Харьков Репутация: 1 Всего: 170 |
Привет всем.
Я давно забыл плюсы и поэтому не буду писать здесь код. Я не очень четко понял задачу в части Непонятно почему выбрана такая реализация: и в базовом, и в дочернем класса будут статические ф-ции, и какая связь между статическими ф-циями базового и дочернего классов? Но меня попросили посмотреть тему и высказаться, поэтому напишу свое видение вопроса концептуально ![]() Десерилизация - это процесс создания и инициализации объекта, аналогичный созданию и инициализации объекта через конструктор. С тем только отличием, что вместо инициализирующих параметров в конструктор передается поток, содержащий полный набор данных объекта. Вместо конструктора marcusmae предлагает использовать вторую виртуальную ф-цию... Ну что ж, можно и так, просто это будет лишний вызов - в любом случае сначала нужно вызвать конструктор десерилизуемого объекта, а потом для него эту виртуальную ф-цию... Но повторяю, пусть пока будет как у marcusmae ![]() Соответственно, для того, чтобы определить, в каком порядке этот поток содержит даннные нашего класса, необходимо построить и зафиксировать граф серилизации. Граф создается при серилизации объекта, при десерилизации данные считываются в соответствии с ним. Для сложного (композитного) объекта подразумевается, что не только он, но и все его поля поддерживают серилизацию, т.е. каждое поле само должно восстановить себя из потока (ну и записать себя в поток при серилизации, конечно). При этом ... Например класс Base содержит в себе поля int, Class1, string. Класс Derived (наследник от Base добавляет bool, Class2, float). Все классы (Base, Derived, Class1 и Class2) наследуют базовый класс
При серилизации вызывается метод Serialize класса Derived, с такой псевдо-реализацией:
где метод Serialize класса Base, с такой псевдо-реализацией:
при десерилизации вызывается конструктор класса Derived, потом метод Deserialize с такой псевдо-реализацией:
метод Deserialize класса Base:
как видно, за позицию курсора потока беспокоиться не нужно - если все классы серилизуют и десерилизуют себя в одном и том же порядке (граф серилизации, определенный в Derived.Serialize используется в Derived.Deserialize), то каждый поток будет его смещать на величину именно своих данных и все будет хоккей.. Закон простой - в каком порядке записывались данные, в таком и читать. Классы сами себя "рассуют" куда нужно (потому что разработчик классов сам определяет что, как и когда писать и читать. Один раз и навсегда, для каждого класса) Здесь явно виден недостаток: постоянные вызовы конструкторов и ф-ций Deserialize... А вот если через конструктор базового класса (с параметром потоком) делать... то его бы не было ![]() и никаких индексов... они просто не имеют смысда в последовательном и единственном потоке. Ну вот и все. Не знаю, понятна ли мысль... Но это ясная и четкая структура, полиморфная и весьма юзабельная. Спасибо за внимание ![]() Это сообщение отредактировал(а) tol05 - 16.2.2008, 19:36 -------------------- На хорошей работе и сны хорошие снятся. |
||||||||||
|
|||||||||||
marcusmae |
|
|||
![]() stravaganza ![]() ![]() Профиль Группа: Участник Сообщений: 874 Регистрация: 26.3.2006 Репутация: 5 Всего: 39 |
tol05, спасибо за ответ!
Согласен, что присутствие спецконструктора полезно в любом случае. А фишка наличия виртуальной функции в том, что с помощью шаблона она возвращает точный тип, а не интерфейс : (плюсифицирую код tol05 ![]()
Здесь внутри был нужный нам конкретный Class1, но при возврате он разобщился до ISerializable, который потом придётся обратно приводить к Class1, правильно? -------------------- ἀπὸ μηχανῆς θεός |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |