28-Sep-03 11:02 Harry Zhurov wrote to Oleksandr Redchuk:
OR>> На самом деле параметры описываются массивами структур во флеше, OR>> массивами указателей на эти массивы и т.п. Всё инициализируется OR>> статически, да, структура меню жёстко забита во флеше. OR>> У каждого параметра в структуре описателя - его тип (int, byte, OR>> string)
HZ> А что такое "увеличить/уменьшить" для строки? Я так понимаю, что HZ> имеется в виду обычная С-строка? Ну я же сказал сразу, что это "так, наляпано", а на самом деле на этом уровне только навигация, редактирование вызывается отсюда:
OR>> , начальный адрес в EEPROM, длина (для строк), min и max значения (для OR>> int/byte), после смены параметра по ещё одному небольшому switch() OR>> вызывается нужная функция Edit() (и уже она делает GetKey() и разбирает OR>> INC/DEC/CLR, по KEY_UP возвращается OR>> на уровень перебора параметров). А inc/dec применяются не к строке, а к символу (а как ещё отредактировать текстовую строку пятью кнопками :-).
OR>> Итого всё меню конфигурирования - это немножко кода OR>> и таблицы констант, которые занимают _гораздо_ меньше места, чем OR>> если бы это всё реализовывать в виде функций или кода по switch().
HZ> Экономия кода достигается исключительно за счет унификации модифицирования HZ> параметров. Это работает только когда параметры однокачественные (числа, HZ> например). Ну, во первых,
18 Sep 03 21:46, you wrote to Dimmy Timchenko: HZ> // ---------------------------------- HZ> ... HZ> if( keySelect.IsClick() ) CurrentParameter++; HZ> if( keyPlus.IsClick() ) CurrentParameter->Increase(); HZ> if( keyMinus.IsClick() ) CurrentParameter->Decrease(); HZ> ... HZ> // ---------------------------------- в приведённом примере тоже как-то параметры могут только увеличиваться и уменьшаться, достаточно ограниченная модель. А когда тебе это написали на C, ты сразу "ну так это ограниченное решение!".
А во-вторых - ты не вчитался. Повторяю. Каждый параметр описывается структурой, в которой кроме его положения в EEPROM задан его тип. По типу мы можем вызвать нужную функцию редактирования. Экономия кода заключается в том, что сам вызов функций чтения и записи EEPROM при редактировании конфигурации имеется в одном единственном месте, т.е. не в каждой виртуальной функции каждого параметра (группы параметров с одинаковым редактированием).
Вместо
CurrentParameter->Load(); // косвенный вызов через vmt // у каждого параметра персонально SomeParameter::Load() { EEread( this, смещение, длина); }
имеем eeparam *parptr = &eep_table[parmano]; // ptr будет использован много раз ниже, при редактировании, // проверке и записи назад EEread( editbuf, parptr->offset, parptr->len); // editbuf - буфер в функции конфигурирования размером с самый // длинный параметр
Аналогично с вызовом редактирующей функции, аналогично с проверкой на min/max для целочисленных параметров -- этот код в единственном месте для всех таких параметров. Из структуры-описателя параметра берутся его min и max значения.
HZ> Как только нужно кроме простого инкремента/декремента делать HZ> еще HZ> что-то разное для разных параметров, то и привет вашим массивам без HZ> функций. Зависит от того, сколько вариантов этого "что-то разное". Будет или switch( parptr->type) { case PARAM_INT: case PARAM_STRING: или (param_editors[parptr->type])( )
OR>> В некотором смысле машина состояний, заданная в виде таблиц переходов,
HZ> А чем принципиально отличается передача потока управления по таблице HZ> переходов от передачи оного по таблице указателей на функции? Принципиальной разницы нет, ты назвал две вещи, которые практически одинаковы (переходы по индексам из массива и переходы по адресам из массива). И обе эти вещи не используются в такой организации меню вообще. В случае с несколькими страницами параметров по кучке параметров в каждом передачи потока управления не происходит. В данном случае "граф" переходов машины примитивен и реализуется на ++parampage
--parampage ++paramno --paramno. В массивы забиты не переходы, а действия в состояниях -- и то не все, действие EEread производится каждом, поэтому в массиве для этого действия хранится информаация "где и сколько".
HZ> И в итоге совсем не та функциональность, как и положено. По сравнению с чем? А то ты уже писал пример для Тимченко, тебе изобразили решение на массивах на C, а вышло "не та функциональность". Перечисли нужную функциональность _ДО_ того, как тебе напишут пример на C.
HZ> Как где-то у HZ> Страуструпа было написано: "Чтобы оценить мощь указателей на функции, А то я не знаю, какая это классная штука, особенно если она на процессоре легко реализуема.
HZ> нужно попытаться сделать то, где они применяются, без них". Знаешь, система меню редактрования параметров может обойтись без указателей на функции очень легко. Сейчас в однокристалках я "вспомнил" подход, который применял для построения многоуровневых иерархических меню в бытность на ДВК. На VT100. А когда в лаборатории появился "Невроз И9.66" и кто-то из не видевших до этого ничего студентов что-то ляпнул в сторону ДВК в духе "этот гроб" - я сел и переделал на ДВК это меню в "как у нортона", да в окошке график вывел, а там КЦГД был, а это 800 по горизонтали :-) Вот там в "активной" части указатели на функции были, а вот при редактировании параметров -- ну не нужны они. Без них код меньше был, несмотря на то, что на PDP работа с указателями превосходна. А мне это жгло, памяти-то 56КБ было на всех с операционкой.
HZ> А чем оно тебе так не нравится? Уж по читабельности, понятности и HZ> логичности вариант с простым линейным массивом однокачественных объектов HZ> куда как лучше, А вот тут я скажу "функциональность не та" :-) У меня там несколько страниц параметров, с разным числом параметров на странице :-))
HZ> чем даже тот кусок псевдокода (а уж что там за монстр в HZ> конечной реализации, можно только представить!) Программа, которая на ДВК вводила картинки с моего контроллера, легонько обрабатывала их (некоторое количество фильтров, гистограмма, яркость/контраст), вырезала куски, показывала на монохромном мониторе (с дизерингом) - вместе с движком меню и его содержимым была около 1100 строк. Правда, с малым довльно количеством комментариев и с форматированием if() { } else { } for(;;) { } и т.д. На 24 строках и при медленных матричниках с постоянным дефицитом бумаги делать if () { } else { } // внимание - пустая строка for() { } жаба давила.
Я тогда страшно гордился тем, какие большие программы я пишу :-)
HZ> Убежден, что ты все это знаешь лучше меня, и тем более не понятно, с HZ> чем ты тут споришь? Я, излагая своё видение, пытаюсь понять - о чём мы спорим :-) Первый момент кажется ясен: Ты считаешь, что C++ можно и НУЖНО применять всем и вплоть до самых мелких программ. Я считаю, что даже на средних программах его стоит применять только тем, кто и так "по жизни" без него не может обойтись, а уж на мелких задачах переходить на него только потому, что он имеет (длинный список) преимуществ на очень больших проектах -- смысла не вижу.
Вторая точка, похоже, сформулирована Алексеем. AB>>> Просто на С принято по другому писать. OR>> Вот именно. И, самое главное, это все не есть "попытка эмуляции HZ> ^^^^^^^^^^^^^ OR>> средствами C поведения C++". HZ> :)) Так это, оказывается, принципиальная позиция?! Ну раз ты обычное и стандартное от рождения языка C упрятывание от пользователя ненужных ему внутренних переменных и функций (а заодно уменьшение размера объектников и сокращение времени работы линкера) при помощи static обозвал "попыткой средствами С проэмулировать поведение C++" -- я считаю своим долгом этот момент особо отмечать :-)))
HZ> попытки эмуляции, ни самой эмуляции - тут нет, самое главное, того же HZ> результата по функциональности, который дают самые обычные массивы HZ> указателей на функции. Т.ч. сравнивать просто нечего. Ну уж не волнуйся. Там, где я считаю указатели на функции осмысленными -- я их применяю. А через период пихания их, очень мне понравивщихся, во все дыры - я прошёл довольно давно. Сейчас уже (mode ? func1 : func2) (param1, param2, param3); или (mode ? struct1 : struct2)->func(param1, param2, param3); не пишу :-) И могу оценить где они нужны, а где надо написать небольшой "движок" а его функциональность забить в массив структур или отдельные массивы. И движок обеспечит навигацию по сложному многоуровневому меню без указателей на функции (за исключенем тех мест, где вызывается действие). А задано всё меню будет при помощи статически инициализированных массивов структру, ссылающихся на другие массивы структур, отдельные структуры, строки и массивы строк. И увидеть на распечатке структуру получившегося меню гораздо проще, чем продираться сквозь menu1.addItem( new menuitem(..., ..., ..., ...) ) не говоря уже о гораздо более коротком коде. Это выходило что-то типа .rc-файла при программировании в винде. (только, чесслово, оно не пыталось его эмулировать :-))
wbr, p.s. кстати, о функциональности. awk, а тем более perl имеют ГОРАЗДО БОЛЬШИЕ возможности, чем sed. Но у меня на машине есть и awk, и sed (перла нет, нужды для себя пока не вижу). Но почему-то я в подавляющем большинстве случаев вызываю sed. Странно, ведь у awk-а то функциональность ого-го...