
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.128] |
![]() |
|
Страницы: (3) 1 [2] 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#16
,
|
|
|
Цитата DelphiLexx @ я не хочу отделять ф-цию Compare от класса, мне не хотелось бы в моем классе, у которого есть метод Sort, чтобы он использовал вещи лежащие вне класса. ...не граммотно это Глупости. Так можно дойти до того, что и функции из модулей StrUtils, Math и т.п. нельзя использовать, поскольку они не принадлежат классу ![]() Во-первых, можно просто функции сравнения дать осмысленное название (типа CompareTMyListItems) и разместить ее в implementation рядом с твоим Sort. Ничего страшного или неграмотного в этом нет - "я так тыщу раз делал" (С) Во-вторых, функция сравнения должна быть "глобальной" по сути, а не формально. Т.е. это может быть и вложенная функция внутри самой Sort при условии, что она не будет обращаться к локальным переменным функции Sort (включая Self и его поля). Пример: ![]() ![]() type TMylist = class(TList) public procedure Sort(Desc:boolean = false);overload; end; procedure tMyList.Sort(Desc:boolean = false); //вложенные функции сравнения function CompareAsc(Item1,Item2:pointer):integer; begin result:=integer(Item1)-integer(Item2); end; function CompareDesc(Item1,Item2:pointer):integer; begin result:=integer(Item2)-integer(Item1); end; begin if Desc then Sort(@CompareDesc) else Sort(@CompareAsc); end; procedure TForm1.Button1Click(Sender: TObject); var L:TMyList; S:string; i:integer; begin L:=TMyList.Create; try L.Add(pointer(2)); L.Add(pointer(1)); L.Add(pointer(3)); L.Sort; S:=''; for i:=0 to L.Count-1 do S:=S+IntTostr(integer(L[i])); L.Sort(true); S:=S+#13#10; for i:=0 to L.Count-1 do S:=S+IntTostr(integer(L[i])); ShowMessage(S); finally L.Free; end; end; |
![]() |
Сообщ.
#17
,
|
|
Felan кошмар, ужос!!!!!!!!!!!!!! У тебя же глобальная функция!!!!!!!!!!!!!
Добавлено Цитата leo @ то она не будет обращаться к локальным переменным функции Sort кста, немного по извращавшись с асмом можно сделать, чтоб она могла к локальным переменным обращаться. |
Сообщ.
#18
,
|
|
|
А вот ненужные глобальные переменные ИМХО это гораздо большее извращение, чем "глобальные" функции ![]() PS: Если метод нужен только для того, чтобы добраться до некоторого св-ва TMyList, то есть вариант использовать в элементах Item ссылку на список Parent:TMyList и в функции сравнения юзать if TMyItem(Item1).Parent.FSign then ... Цитата jack128 @ кста, немного по извращавшись с асмом можно сделать, чтоб она могла к локальным переменным обращаться В отношении Sort шибко сомневаюсь, т.к. она использует рекурсивные вызовы QuickSort, в которую передается не сам TList, а только массив указателей. Поэтому уже на втором уровне вложенности все локальные переменные Sort улетят далеко-далеко ![]() |
![]() |
Сообщ.
#19
,
|
|
Цитата leo @ В отношении Sort шибко сомневаюсь, т.к. она использует рекурсивные вызовы QuickSort, в которую передается не сам TList, а только массив указателей. Поэтому уже на втором уровне вложенности все локальные переменные Sort улетят далеко-далеко ![]() Ну вот такой код: ![]() ![]() procedure TForm3.Test; var LocalCounter: Integer; function LocalCompare(Item1, Item2: Integer): Integer; begin Inc(LocalCounter); Inc(GlobalCounter); Result := Item1 - Item2; end; var I: Integer; L: TList; begin Randomize; GlobalCounter := 0; LocalCounter := 0; L := TList.Create; try for I := 0 to 100 - 1 do L.Add(Pointer(Random(100))); L.Sort(LocalProcCaller(@LocalCompare).Proc); // вся магия в LocalProcCaller. там динамически генерится код, подправляющий стек. Memo1.Lines.Clear; for I := 0 to L.Count - 1 do Memo1.Lines.Add(IntToStr(Integer(L[I]))); Memo1.Lines.Add(Format('LocalCount = %d, GlobalCounter = %d', [LocalCounter, GlobalCounter])) // LocalCount всегда равен GlobalCounter. AV нигде нет. Сортируется тоже нормально.. finally L.Free; end; end; Скажу чесно сам я в асме не силен, идею почерпнул из модуля AsyncCalls.pas. Если интересно могу выложить исходники LocalProcCaller, может багу кто найдет. |
Сообщ.
#20
,
|
|
|
jack128 ААААА!!!!!!!!!! Убей меня об стенку скореее!!!!!!!!!!
![]() Так-то да, но наследники то уже будут метод использовать, а не глобальную функцию, однажды и навсегда скрутую в нутри класса. leo Так ты самую вкусность скрыл. Теперь извне классу не подставишь "компоратор". Если раньше можно было для любого объекта сделать функцию сравнения, передать ее в список и он бы сортировал что угодно, то теперь только то, что ты пропишешь и ничего более. |
Сообщ.
#21
,
|
|
|
Может хватит, а? А то впечатление, что здесь одни извращенцы собрались.
Функция сравнения, как я уже сказал, сделана именно функцией совсем не случайно. Можно было ее сделать методом класса, но не сделали потому, что контейнер TObjectList может хранить и "чужие" объекты, у которых метода сравнения нет и сделать нельзя (о хелперах не говорю). |
Сообщ.
#22
,
|
|
|
Цитата jack128 @ вся магия в LocalProcCaller. там динамически генерится код, подправляющий стек Ну ежели динамически, то конечно ![]() Цитата Felan @ Так ты самую вкусность скрыл. Теперь извне классу не подставишь "компоратор". Если раньше можно было для любого объекта сделать функцию сравнения, передать ее в список и он бы сортировал что угодно, то теперь только то, что ты пропишешь и ничего более "Скрыл" только для примера, по заявкам трудящихся антиглобалистов ![]() К тому же за счет overloaded оригинальный Sort остается - подставляй, что хочешь Добавлено Цитата Romkin @ Можно было ее сделать методом класса, но не сделали потому, что контейнер TObjectList может хранить и "чужие" объекты, у которых метода сравнения нет и сделать нельзя (о хелперах не говорю) Странное объяснение ![]() |
Сообщ.
#23
,
|
|
|
Цитата leo @ Значит сравнивать "несравнимые" элементы разрешили (через функцию), но иметь при этом доступ к некому объекту (владельцу функции сравнения) - ни-изя ?! А зачем и с какой целью? Тебе даны две сущности - их и сравни. Заодно при смене контейнера функцию менять не надо, она уже есть. Каким образом результат сравнения двух сущностей может зависеть от экземпляра контейнера, в котором они содержатся? |
![]() |
Сообщ.
#24
,
|
|
Цитата Romkin @ Каким образом результат сравнения двух сущностей может зависеть от экземпляра контейнера, в котором они содержатся? э-э-э. TStrings.CompareStrings например. |
Сообщ.
#25
,
|
|
|
Цитата jack128 @ э-э-э. TStrings.CompareStrings например. И шо? Там строки, все сразу понятно. И от контейнера тоже не зависит. Добавь к этому, что TStrings - абстрактный класс, ты обязан написать потомка. А вот TStringList.CustomSort опять использует функцию, экземпляр в которую передается только потому, что неизвестно, какой элемент ты хочешь сравнивать, саму строку, или объект, и даются индексы. И для реализации сравнения не нужно писать потомка. Это удобно и разумно. И криминала здесь никакого нет. Вообще. |
![]() |
Сообщ.
#26
,
|
|
Цитата Romkin @ И от контейнера тоже не зависит. ну как же - смотрим его наследника, TStringLIst и что мы видим ?? Функция сравнения использует данные класса. |
Сообщ.
#27
,
|
|
|
Цитата jack128 @ ну как же - смотрим его наследника, TStringLIst и что мы видим ?? Функция сравнения использует данные класса. Хм. Действительно. Выбор нужной функции для сравнения. Но абсолютно не мешает подать соответствующую функцию compare в Sort. Leo чуть выше практически это и сделал. Так что криминала все равно нет. А вот если бы TList использовал свою виртуальную функцию, тебе пришлось бы на каждый чих писать его наследника. |
![]() |
Сообщ.
#28
,
|
|
Цитата Romkin @ А вот если бы TList использовал свою виртуальную функцию, а никто этого и не предлагает. ПРедлагают чтоб List.Sort принемал не функцию, а метод. |
Сообщ.
#29
,
|
|
|
Цитата Romkin @ Каким образом результат сравнения двух сущностей может зависеть от экземпляра контейнера, в котором они содержатся? Во-первых, не обязательно самого контейнера, т.к. метод сравнения может принадлежать и не контейнеру, а любому другому объекту (например владельцу этого контейнера). Во-вторых, сущности могут сравниваться по разному и правило сравнения ес-но задают не сами сущности, а тот кто их сравнивает. Например, можно написать две разные функции сравнения для сортировки по возрастанию и по убыванию, а можно несколько поступиться быстродействием и впихнуть все в одну функцию, инвертирующую рез-т сравнения в завис-ти от некоторого св-ва самого контейнера или другого объекта. В общем, задачи разные бывают и впадать из одной крайности (ха-ачу метод) в другую (ни-изя метод) - имхо не стоит ![]() |
Сообщ.
#30
,
|
|
|
Цитата leo @ В общем, задачи разные бывают и впадать из одной крайности (ха-ачу метод) в другую (ни-изя метод) - имхо не стоит А это не крайность, это вопрос удобства. В данном случае метод просто унаследован от TList, а там чаше всего требование именно метода ограничивает, мало ли на что я там ссылки хранить буду. А мотивов переделывать Sort на получающий метод я не вижу. |