Здравствуйте, FWP, Вы писали:
FWP>... Свойства — это атрибут компонентно-ориетированного языка. Компоненты в Delphi, а теперь и в C#?, позволяют затачивать IDE под себя...
Свойства — это более близкий человеческому способ настраивать поведение и работу объектов (классов). При этом возможна именно логическая (абстракционная) настройка, меняющаяя сразу несколько переменных-членов класса и даже других свойств (опосредованно этих переменных-членов и функций-членов). За модификацией свойства может следовать как модификация переменных-членов, так и функций-членов (методов) класса.
По сути, это даже можно сравнить с шаблонами C++ — задача та же упростить программисту жизнь, скрыть от него подробности реализации, сократить текст программы, оставив только функциональный смысл.
И при этом (при пользовании свойствами) можно использовать прелести наследования, инкапсуляции и полиморфизма.
По моему, по меньшей мере глупо говорить, что С++ свойства ни к чему. К удобному быстро привыкаешь...
Здравствуйте, WolfHound, Вы писали:
WH>BCB это глюкалово страшное. Если все это перенести в дельфи то точно хана дельфе. S>>При всей твоей рекламе шаблонов, лично я совершенно безболзненно обхожусь без них, WH>Ну некоторые и на С безболезненно пишут, а некоторые и на асме. S>>но от возможности их применения не отказался бы. Еще раз давай совсем немного подождем,а на данном этапе Delphi уже исчерпал себя. WH>Вот я и говоряю что .НЕТ2 ждать надо.
Применение Маккросов и Шаблонов наложили отпечаток и на сам язык, так перегрузки операций и функций прекрасно вписываются в Шаблонную систему и неявное приведение типов, но их переизбыток иногда ведет к непониманию кода, особенно когда перегруженная функция имеет совсем другой смысл, но написание ее будет темже. Перегрузка операторов для элементарных типов тоже может вести к неправильному восприятию (например сложение указателей и неявное приведение к LongWord).
Отсутствие шаблонов в Delphi, заставляет мыслить Виртуально, а не Шаблонно.
Вернемся к сортировке. Для элементарных типов шаблоны впереди планеты всей, но со сложными структурами, когда нужно сортировать по любому сочетанию полей и во время выполнения программы шаблоны бессмыслены, если вспомнить комбинаторику и посчитать все сочетания.
Решение выглядит приблизительно так.
unit FLDUnit;
{$R-,T-,X+,H+,B-}interface
Uses SysUtils;
Type
TFld = Class(TObject)
Len,Offset:Cardinal;
protected
Procedure SetCompValue(Const p:Pointer); virtual; abstract;
Function GetAsString(Const p:Pointer):string; virtual; abstract;
Procedure SetAsString(Const p:Pointer; Const Value:String); virtual; abstract;
Public
Procedure Swap(Const p1,p2:Pointer); virtual; abstract; // для любителей оптимизации на AsmFunction CompareFlds(Const p1,p2:Pointer):Integer; virtual; abstract;
Function CompareFldWithCompValue(Const p:Pointer):Integer; virtual; abstract;
Procedure SetValue(Const p,buffer:Pointer); virtual; abstract;
Procedure GetValue(Const p,buffer:Pointer); virtual; abstract;
Property CompValue:Pointer write SetCompValue;
Property AsString[Const P:Pointer]:String Read GetAsString write SetAsString;
Constructor Create; Virtual;
end;
TFldClass = class of TFld;
TFldArray = Array of TFld;
TMultiFlds = Class(TFld)
PointerOfCompValue:Pointer;
Fields : TFldArray;
CompFlds: TFldArray;
HiCompIndex:Cardinal;
Public
Function CompareFlds(Const p1,p2:Pointer):Integer; Override;
Function CompareFldWithCompValue(Const p:Pointer):Integer; override;
Procedure SetCompValue(Const p:Pointer);Override;
Procedure SetFldValue(Const i:Cardinal; Const p,buffer:Pointer);
Procedure GetFldValue(Const i:Cardinal; Const p,buffer:Pointer);
Procedure SetCompareFields(CmpFld:array of TFLD);
Constructor Create; override;
Constructor CreateFromFldClass(Flds: array of TFldClass); Virtual;
Constructor CreateFromFlds(Flds: array of TFld);Virtual;
destructor Destroy; override;
end;
implementation{ TMultiFlds }function TMultiFlds.CompareFlds(const p1, p2: Pointer): Integer;
Var I:Integer;
Fld:Tfld;
begin
For i:=0 To HiCompIndex Do
Begin
Fld:=CompFlds[i];
result:=Fld.CompareFlds(Pointer(Cardinal(p1)+Fld.Offset),Pointer(Cardinal(p2)+Fld.Offset));
If Result<>0 Then
Break
end;
end;
function TMultiFlds.CompareFldWithCompValue(const p: Pointer): Integer;
Var I:Integer;
Fld:Tfld;
begin
For i:=0 To HiCompIndex Do
Begin
Fld:=CompFlds[i];
result:=Fld.CompareFldWithCompValue(Pointer(Cardinal(p)+Fld.Offset));
If Result<>0 Then
Break
end;
end;
constructor TMultiFlds.Create;
begin
Inherited Create;
end;
constructor TMultiFlds.CreateFromFldClass(Flds: array of TFldClass);
Var i:Integer;
begin
inherited Create;
SetLength(self.Fields,Length(Flds));
len:=0;
For i:=0 to Length(Flds)-1 do
Begin
Fields[i]:=Flds[i].Create;
Fields[i].Offset:=len;
Inc(len,Fields[i].Len);
end;
end;
constructor TMultiFlds.CreateFromFlds(Flds: array of TFld);
Var i:Integer;
begin
inherited Create;
SetLength(self.Fields,Length(Flds));
len:=0;
For i:=0 to Length(Flds)-1 do
Begin
Fields[i]:=Flds[i];
Fields[i].Offset:=len;
Inc(len,Flds[i].Len);
end;
end;
destructor TMultiFlds.Destroy;
Var i:Integer;
begin
For i:=0 To Length(Fields)-1 Do
Fields[i].Free;
inherited;
end;
procedure TMultiFlds.GetFldValue(const i: Cardinal; const p,
buffer: Pointer);
begin
Fields[i].GetValue(p,buffer);
end;
procedure TMultiFlds.SetCompareFields(CmpFld: array of TFLD);
Var i:integer;
begin
HiCompIndex:=Length(CmpFld);
SetLength(CompFlds,HiCompIndex);
Dec(HiCompIndex);
For i:=0 to HiCompIndex Do
CompFlds[i]:=CmpFld[i];
end;
procedure TMultiFlds.SetCompValue(const p: Pointer);
Var i:Integer;
Fld:Tfld;
begin
For i:=0 To Self.HiCompIndex Do
Begin
Fld:=CompFlds[i];
Fld.CompValue:=Pointer(Cardinal(p)+Fld.Offset);
end;
end;
procedure TMultiFlds.SetFldValue(const i: Cardinal; const p,
buffer: Pointer);
begin
Fields[i].SetValue(p,buffer);
end;
end;
Теперь переопределив TFld всех элементарных типов Мы имем два класса которые могу применять в любых функциях сравнения, динамического отображения и редактирования, отображать и редактировать таблицы БД на основании их заголовков полей итд.
Вот пример сортировки
Procedure SortArrayFld(Var a;Fld:TFld);
Var
BeginArray,len:Cardinal;
procedure QuickSort(L, R: Integer);
var
I, J: Integer;
begin
I :=L;
J :=R;
Fld.CompValue:=Pointer( L+(( ((r-l) div len) shr 1)*len));
repeat
while Fld.CompareFldWithCompValue(Pointer(I)) < 0 do
Inc(I,Len);
while Fld.CompareFldWithCompValue(Pointer(J)) > 0 do
Dec(J,len);
if I <= J then
begin//Fld.Swap(Pointer(I),Pointer(J));
Q_SwapMem(Pointer(i),Pointer(j), Len);
Inc(I,Len);
Dec(J,Len);
end;
until I > J;
if L < J then
QuickSort(L,J);
if R>I then
QuickSort(I,R);
end;
Begin
Len:=fld.Len;
BeginArray:=PCardinal(@a)^;
QuickSort(BeginArray,BeginArray+(PCardinal(BeginArray-4)^-1)*len);
End;
И в отличие от шаблонов, скорость падает, но я имею универсальность, а при выборе оптимальных алгоритмов в прктических диапозонах вычислений ловит тысячные секунды не имеет смысла. Все зависит от задачи.
и солнце б утром не вставало, когда бы не было меня
WH>>>Ну и нахрена это надо? M>>Для однообразности и простоты. Все объекты ведут себя с памятью одинаково. Мозги не парятся. WH> Супер аргумент.
Именно. Всё должно быть как можно проще.
WH>А слабо integer by ref сделать? Я не знаю зачем но в С++ это делается на раз boost::shared_ptr<int>
Именно, что слабо. Никому не нужная экзотика.
WH>>>В том то и засада что не всегда объект можно просто скопировать. M>>А все объекты byref, то есть ничего и не копируется. Чтобы сделать копию, нужно как и в .NET вызвать какой-нибудь Clone. WH>Да ради бога. В С++ можно тоже пользоваться только by ref и что? Просто я предпочитаю иметь выбор.
В некоторых случаях ограничения выбора — благо. К примеру, на мосту через Днепр перильца есть.
WH>>>При написании ГУИ к БД согласен, а вот на счет всего остального. M>>Ты что, предлагаешь и в браузерах скрипты на C++ писать? Или ты какое-то конкретное "остальное" имеешь ввиду? WH>Ты дурочку не валяй. Прекрасно понял о чем речь.
Прекрасно понял. Когда ты говоришь "всё остальное", это означает "узкий круг задач, которыми я сейчас занимаюсь"
WF>А насчет синтаксиса — тоже не очень навороченно, описание поля, да в конструкторе свойству адрес внешнего класса дать. И все. В C++ бывают ситуации с гораздо более тяжелым синтаксисом. Так что они не сильно-то и нужны.
Здравствуйте, Serginio1, Вы писали:
S> Очень даже правда и любой Дельфист это скажет перешедший или изучающий Net. Подождем Delphi.Net и тогда уж сравним с C# ( уже по анонсам много интересного и много отличного от C#) Хотя это два языка Брата и родитель у них один Андреас Хейлсберг. Прошу не обижаться поклонников Вирта (я сам его поклонник).
Да уж братья. И уж совсем не ясно каким боком Вирт к Шарпу?
... << RSDN@Home 1.1 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Serginio1, Вы писали:
S>> Очень даже правда и любой Дельфист это скажет перешедший или изучающий Net. Подождем Delphi.Net и тогда уж сравним с C# ( уже по анонсам много интересного и много отличного от C#) Хотя это два языка Брата и родитель у них один Андреас Хейлсберг. Прошу не обижаться поклонников Вирта (я сам его поклонник).
VD>Да уж братья. И уж совсем не ясно каким боком Вирт к Шарпу?
Вирт-Паскаль-Хейлсберг-Turbo Pascal-Delphi-Net-C#. (Типизация, иерархия классов, сериализация, компонентность)
и солнце б утром не вставало, когда бы не было меня
M>>Языки, в которых поддерживаются свойства являются компонент-ориентированными. Ну вот не могу сказать почему так выходит, а реальность такова.
WH>Это ни как не связано. В С++ я могу эмулировать свойства, а некоторые компиляторы поддерживают их в качестве расширения.
Ну, в Дельфи тоже можно много чего эмулировать. Те же шаблоны можно эмулировать.
M>>А я не вижу ничего хорошего в том, что C++ не понимают люди без образования. WH>А я не вижу ни чего хорошего в том что людей без образования допускать к работе ибо всеравно глаз да глаз за ними нужен. WH>Ну не дело это домохозяйкам программы писать.
Ага. А в начале прошлого века говорили: не дело это, домохозяек за руль пускать. Но когда машины стали удобны, надёжны и просты в управлении, домохозяйки сели за руль.
С языками/компьютерами/программированием будет точно то же самое.
M>>Если тебе непонятны эти преимущества, возможно они тебе и не нужны. WH>Преймущества .НЕТ это Reflection и Reflection.Emit это сильно, а все остальное фигня.
Именно! Правда, как ты говоришь, разработчики COM'а тебя не поймут
M>>Мало ли у кого какая отрасль работы. А мне вот нужно, чтобы мой код был понятен [censured]'ам, и свойство-ориентированность тоже удобна. WH> Вот это действительно круто.
Всё дело в том, что иногда я сам являюсь [censured]'ом, и забочусь о том, чтобы самому в своём коде разобраться.
WH>>>А почему нет? M>>Потому, что рантайм-библиотеки не писались для этого применения. Мало ли, каким образом там память выделяется, какие дополнительные функции вызываются. WH>STL и CRT это немного разные вещи не находишь?
Я не знаю, насколько STL зависит от платформы.
M>>В некоторых местах в драйвере нельзя никакой лишней работы делать. Чтобы не дай бог ни подкачки, ни задержки никакой не было. Ну, закрепишь ты свой собственный код в памяти от свопирования. Но служебные библиотеки мало ли как там закреплять — это отдельно тестировать нужно.
WH>Слова человека не знающего о существовании такого понятия в STL как allocator.
Для профессионального программиста на C++ ты делаешь удивительно тривиальные выводы. Да, я не знаю, что такое STL allocator. И именно поэтому, я не понимаю твоего аргумента
WH>Но даже если забить на STL то ни что не мешает просто пользоваться всеми благами шаблонов.
Думаю, без хороших библиотек шаблоны среднеполезны.
Здравствуйте, Serginio1, Вы писали:
VD>>Да уж братья. И уж совсем не ясно каким боком Вирт к Шарпу? S> Вирт-Паскаль-Хейлсберг-Turbo Pascal-Delphi-Net-C#. (Типизация, иерархия классов, сериализация, компонентность)
Вирт создал обычный Паскаль. А на Дельфи вроде как даже плевался. Он тут точно не причем.
... << RSDN@Home 1.1 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Serginio1, Вы писали:
VD>>>Да уж братья. И уж совсем не ясно каким боком Вирт к Шарпу? S>> Вирт-Паскаль-Хейлсберг-Turbo Pascal-Delphi-Net-C#. (Типизация, иерархия классов, сериализация, компонентность)
VD>Вирт создал обычный Паскаль. А на Дельфи вроде как даже плевался. Он тут точно не причем.
Были еще Модула и (уже забыл Обтерон вроде) тоже ООП. Главное идеи и их преемственность. А так как я вырос еще из Виртовского Паскаля, то эти переходы для меня очень просты.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, mihailik, Вы писали:
WH>>>>При написании ГУИ к БД согласен, а вот на счет всего остального. M>>>Ты что, предлагаешь и в браузерах скрипты на C++ писать? Или ты какое-то конкретное "остальное" имеешь ввиду? WH>>Ты дурочку не валяй. Прекрасно понял о чем речь.
M>Прекрасно понял. Когда ты говоришь "всё остальное", это означает "узкий круг задач, которыми я сейчас занимаюсь"
Вот это, кстати, в точку. Этим, кстати, многое определяется в высказываниях.
Здравствуйте, mihailik, Вы писали:
M>И как это работает? Посдчёт ссылок, как я понимаю. M>Это старьё, и алгоритм типа AddRef/Release давно признан архитектурно убогим. На цикличных ссылках не пашет.
Зато быстро, эффективно и детерминировано. К тому же есть механизм слабых ссылок, для разрешения проблемы циклических ссылок.
P.S. А у тебя есть другой вариант? Более новый, чем циклические ссылки, с детерминированным освобождением? Интересно было бы послушать.
P.P.S. Кстати, кем признан ? Мировым сообществом Java/.NET программистов?
Здравствуйте, VladD2, Вы писали:
VD>Вирт создал обычный Паскаль. А на Дельфи вроде как даже плевался. Он тут точно не причем.
Вирт создал не только Pascal. Были еще Modula, Modula-2, Modula-3. TurboPascal и Delphi много чего почерпнули из них. Создатели Delphi привнесли в язык много модных, но потенциально опасных вещей. Поэтому он и "плевался". И если Modula-2 и TurboPascal — близняшки, то Oberon-2 и Delphi7 — троюродные братья
M>>И как это работает? Посдчёт ссылок, как я понимаю. M>>Это старьё, и алгоритм типа AddRef/Release давно признан архитектурно убогим. На цикличных ссылках не пашет.
WF>Зато быстро, эффективно и детерминировано. К тому же есть механизм слабых ссылок, для разрешения проблемы циклических ссылок.
Ага. И это "продают" под видом простоты и надёжности.
WF>P.S. А у тебя есть другой вариант? Более новый, чем циклические ссылки, с детерминированным освобождением? Интересно было бы послушать.
А что такое детерминированное освобождение? Ты можешь описать это другим образом кроме как "также, как AddRef/Release"?
WF>P.P.S. Кстати, кем признан ? Мировым сообществом Java/.NET программистов?
Здравствуйте, mihailik, Вы писали:
M>Ага. И это "продают" под видом простоты и надёжности.
Ну да, согласен, простой домохозяйке это не доступно. С++ — это не язык для домохозяек, как это уже не раз отмечалось. Он дико сложен, но и чрезвычайно гибок. В принципе, циклические ссылки — не так страшны, как тебе кажется.
WF>>P.S. А у тебя есть другой вариант? Более новый, чем циклические ссылки, с детерминированным освобождением? Интересно было бы послушать.
M>А что такое детерминированное освобождение? Ты можешь описать это другим образом кроме как "также, как AddRef/Release"?
Когда на объект нет ссылок, он сразу умирает. Все просто . Или если использовать scoped_ptr, когда указазатель выходит из области видимости. Или, например, автоматическое отписывание от события. На C++ реализуется чрезвычайно просто. В конструкторе, например, подписываемся, а в деструкторе — автоматически отписываемся.
WF>>P.P.S. Кстати, кем признан ? Мировым сообществом Java/.NET программистов?
M>А ты сам разве не согласен с мировым сообществом?
Не совсем. Где-то GC лучше, где-то C++-ый подход.
Я не понимаю, что все к этим циклическим ссылкам привязались . Не так уж часто они встречаются. Гораздо чаще встречаются повисшие на событиях делегаты в .NET-е, и насколько мне известно, эта проблема красиво не решается. Все эти решения через WeakDelegates — удаление гланд через задний проход. А все из-за отсутствия автоматического вызова деструкторов. Приходится два раза думать об одном и том же. И если подписывание — это часть логики, которую за тебя, разумеется, никто не сделает, то отписывание часто — всего лишь освобождение ресурсов. Которое, опять таки, довольно часто может быть автоматизировано.
M>>Ага. И это "продают" под видом простоты и надёжности.
WF>Ну да, согласен, простой домохозяйке это не доступно. С++ — это не язык для домохозяек, как это уже не раз отмечалось. Он дико сложен, но и чрезвычайно гибок.
Согласен.
WF>В принципе, циклические ссылки — не так страшны, как тебе кажется.
Это как так "не так страшны"? Зависнет в памяти целый граф, типа там большая структура бизнес-объектов — это не страшно? Хм...
WF>>>P.S. А у тебя есть другой вариант? Более новый, чем циклические ссылки, с детерминированным освобождением? Интересно было бы послушать.
M>>А что такое детерминированное освобождение? Ты можешь описать это другим образом кроме как "также, как AddRef/Release"?
WF>Когда на объект нет ссылок, он сразу умирает. Все просто .
Куда там! Следуя этому определению ты от циклических ссылок никак не уйдёшь.
WF>Или если использовать scoped_ptr, когда указазатель выходит из области видимости.
А без C++ можно определение дать? А то получается, детерминированное осовобождение — чисто внутренне понятие C++.
WF>Я не понимаю, что все к этим циклическим ссылкам привязались . Не так уж часто они встречаются.
Если важный сервер в банке будет падать "не так уж часто", ребята будут очень недовольны. Так что категории "часто/нечасто" тут не совсем правильны.
WF>Гораздо чаще встречаются повисшие на событиях делегаты в .NET-е, и насколько мне известно, эта проблема красиво не решается.
А в чём, собственно, проблема-то? Ну да, делегаты создают жёсткую ссылку на объект и не дают его выбросить. Ну оно так и задумывалось, под это и написано.
WF>Все эти решения через WeakDelegates — удаление гланд через задний проход.
Естественно.
WF>А все из-за отсутствия автоматического вызова деструкторов. Приходится два раза думать об одном и том же. И если подписывание — это часть логики, которую за тебя, разумеется, никто не сделает, то отписывание часто — всего лишь освобождение ресурсов. Которое, опять таки, довольно часто может быть автоматизировано.
Проблема автоматического вызова деструкторов — та же архитектурная проблема циклических ссылок.
Здравствуйте, mihailik, Вы писали:
M>А без C++ можно определение дать? А то получается, детерминированное осовобождение — чисто внутренне понятие C++.
Детерминированное == определенное. Т.е когда точно известен момент (и им можно управлять), например, смерти объекта.
WF>>Я не понимаю, что все к этим циклическим ссылкам привязались . Не так уж часто они встречаются.
M>Если важный сервер в банке будет падать "не так уж часто", ребята будут очень недовольны. Так что категории "часто/нечасто" тут не совсем правильны.
Почему нет? 100% надежных систем нет. Я всего лишь хотел сказать, что вероятность встречи с такой ситуацией, на мой взгляд, не очень высока. Хотя это архитектурная проблема.
Кстати, потенциальные циклические графы можно ведь и автоматически искать. Например есть модель в Розе ("умный" указатель — ассоциация с неким стереотипом, например, "shared ptr"). А потом просто все циклы таких ассоциаций искать. На бейсике наверняка довольно быстро ищется.
WF>>Гораздо чаще встречаются повисшие на событиях делегаты в .NET-е, и насколько мне известно, эта проблема красиво не решается.
По аналогии. Если важный сервер в банке будет падать "не так уж часто" (от нехватки памяти), ребята будут очень недовольны. И решается эта проблема аналогично C++-ым утечкам — профайлером. Между прочим, довольно распространенная ошибка. Видимо программисты думают, что GC за них все освободит и забывают обнулять ссылки, отписывать делегаты — отсюда получаются утечки памяти. Конечно, на объекты есть ссылки, но от этого они не перестают быть утечками — память тратится впустую.
M>А в чём, собственно, проблема-то? Ну да, делегаты создают жёсткую ссылку на объект и не дают его выбросить. Ну оно так и задумывалось, под это и написано.
Да.
WF>>А все из-за отсутствия автоматического вызова деструкторов. Приходится два раза думать об одном и том же. И если подписывание — это часть логики, которую за тебя, разумеется, никто не сделает, то отписывание часто — всего лишь освобождение ресурсов. Которое, опять таки, довольно часто может быть автоматизировано.
M>Проблема автоматического вызова деструкторов — та же архитектурная проблема циклических ссылок.
Проблема в том, что когда я подписываю на событие (например, в конструкторе, да еще и на статическое событие) — это часть логики. Если я забуду подписаться, это, скорее всего, легко обнаружится. А вот отписывание — уже не часть логики, я могу с легкостью забыть отписаться и получу утечку. Вот почему "умные" указатели существенно облегчают работу — нужно лишь захватить ресурс, а освободится он сам, причем управляемо.