![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
класс, который не нужно создавать.
@!!ex © (2008-11-10 17:48:00)Можно ли както сделать, чтобы класс создавался и удалялся автоматически, без явного TClass.Create(); ?
тоесть:
TVector = class;
Обычно делаю так:
Function ();
var
v:TVector;
begin
v:=TVector.Create();
v:=a+b;
v.free();
end;
А хочется так:
Function ();
var
v:TVector;
begin
v:=a+b;
end;
Slym (2008-11-12 18:06:00) [1]Опиши свои Variant типы (CustomVariant) получиш и астоубийство и создание и некоторые операции +-*/
@!!ex (2008-11-11 19:56:00) [2]> [18] oxffff © (11.11.08 19:24)
Как раз работает.
Я просто объяснил, почему не хочется использовать фунации.
Операторы почти всегда нагляднее.
Почти - потому что если оператор переопределен не логично, это только запутывает код.
oxffff (2008-11-11 19:30:00) [3]
> Можешь использовать способ.
Мой способ. ;)
oxffff (2008-11-11 19:29:00) [4]
> jack128_ (11.11.08 18:32) [15]
>
> > Анонимный метод это интерфейс.
>
> Ха. Блин, имхо - не правельно. ТОчнее то что анонимные
> методы - как интефейсы реализованы - это понятно, но лично
> мне не ясно, нафиг эту внутреннюю кухню наружу выносить.
> .
Что неправильно? То что захват происходит при помощи программиста.
Можешь использовать способ. Он там тоже в комментах озвучен.
procedure MyDestroy(obj:Tobject);
asm
push eax;
mov eax,[eax+12];
call Tobject.Free;
//No necessity for finalization, just Freemem
//And there is no valid RTTI for finalization
pop eax;
call System.@Freemem;
end;
const DestroySlot:pointer=@MyDestroy;
procedure PatchVMT(obj:Tobject);
asm
mov [eax],offset DestroySlot+4;
end;
class function TSmartPointerFromRussia'T'.Wrap2(const AValue: T): TFunc'T';
begin
PatchVMT(Tobject(dword(@AValue)-12));
Result := function: T
begin
Result := AValue;
end;
end;
oxffff (2008-11-11 19:24:00) [5]
> @!!ex © (11.11.08 19:15) [17]
А что перегрузка операторов не работает?
@!!ex (2008-11-11 19:15:00) [6]> [16] Правильный$Вася (11.11.08 18:47)
Так и сделал.
Мешает то, что код превращается в свалку.
Сравните:
Function GetNormal(const v1,v2,v3:TVector4f):TVector4f;
begin
Result:=(v2-v1)*(v3-v1);
Result.Normalize();
end;
Function GetNormal(const v1,v2,v3:TVector4f):TVector4f;
begin
Result:=Normalize(Cross(Sub(v2,v1),Sub(v3,v1));
end;
Правильный$Вася (2008-11-11 18:47:00) [7]
> Есть два типа TVector4f и TMatrix4x4f. Оба - рекорды.Оба
> типа очень активно используются.Матрица умеет усножать себя
> на вектор оператором.Сейчас понадобилось научить вектор
> умножать себя на матрицу.
можешь сделать функцию, что мешает?
jack128_ (2008-11-11 18:32:00) [8]
> Анонимный метод это интерфейс.
Ха. Блин, имхо - не правельно. ТОчнее то что анонимные методы - как интефейсы реализованы - это понятно, но лично мне не ясно, нафиг эту внутреннюю кухню наружу выносить..
> он предложил этот способ
не сильно лудше его самого первого смарт поинтера, если чесно:
Новый вариант:
var
Obj: TFunc<TObject>
begin
Obj := THandleObject<TObject>.Create(TObject.Create);
end;
Старый вариант:
var
Obj: TObject;
begin
Obj := TSmatPointer<TObject>.Create(TObject.Create).Value;
end;
oxffff (2008-11-11 08:43:00) [9]
> jack128_ (10.11.08 23:11) [10]
Если интересно историю можешь посмотреть мою переписку c Barry Kelly в его блоге.
Сначало было
http://barrkel.blogspot.com/2008/11/reference-counted-pointers-revisited.html
после переписки
Sergey Antonov aka oxffff said...
@Barry
perfectly, since anonymous method has Ref counting semantic and is used by outer consumer, there is no need in inner shared TSmartPointerController.
So we can remove 2 extra objects.
он предложил этот способ
> There was a little to and fro in the comments on yesterday's
> post on more fluent smart pointers
http://barrkel.blogspot.com/2008/11/somewhat-more-efficient-smart-pointers.html
oxffff (2008-11-11 08:38:00) [10]
> jack128_ (10.11.08 23:11) [10]
>
> > TObjectHandle<T: class> = class(TInterfacedObject, TFunc<T>)
>
> а что означает эта запись??
>
> TFunc<T> объявлен вот так:
> TFunc<TResult> = reference to function: TResult;
>
> что то не вьеду, как класс может наследоваться от анонимного
> метода??
Анонимный метод это интерфейс.
Loginov Dmitry (2008-11-11 00:19:00) [11]может все-таки с .Create() будет проще?)))
@!!ex (2008-11-11 00:11:00) [12]> Переходи на 2009.
две штуки баксов на покупку не одолжите? :)))
jack128_ (2008-11-10 23:11:00) [13]
> TObjectHandle<T: class> = class(TInterfacedObject, TFunc<T>)
а что означает эта запись??
TFunc<T> объявлен вот так:
TFunc<TResult> = reference to function: TResult;
что то не вьеду, как класс может наследоваться от анонимного метода??
oxffff (2008-11-10 22:48:00) [14]
> @!!ex © (10.11.08 21:25) [6]
> > [5] oxffff © (10.11.08 21:08)
>
> 2009? :))
> У меня TDE...
Переходи на 2009. См. [7].
oxffff (2008-11-10 21:30:00) [15]
> procedure TForm2.FormCreate(Sender: TObject);
> var a,b:TSomeClass<TDemoObject>;
> c:TFunc<TDemoObject>;
> begin
> c:=a+b;
> c:=a;
> end;
Ну естественно можно С.Classname и т.д.
oxffff (2008-11-10 21:26:00) [16]
> oxffff © (10.11.08 21:08) [5]
Усложняем задачу, делая автоматическое освобождение объектов.
Get Ready!!!
TDemoObject=class
procedure BeforeDestruction;override;
end;
TObjectHandle<T: class> = class(TInterfacedObject, TFunc<T>)
private
FValue: T;
public
constructor Create(AValue: T);
destructor Destroy; override;
function Invoke: T;
end;
TSomeClass<T: class,constructor> = record
public
class operator Implicit(const AValue: TSomeClass<T>): TFunc<T>;
class operator Add(const AValue:TSomeClass<T>;AValue2:TSomeClass<T>): TFunc<T>;
end;
procedure TDemoObject.BeforeDestruction;
begin
showmessage('Этот пройдешь как дети в школу');
inherited;
end;
class operator TSomeClass<T>.Implicit(const AValue: TSomeClass<T>): TFunc<T>;
begin
showmessage('Implicit cast');
exit(TObjectHandle<T>.create(T.create));
end;
class operator TSomeClass<T>.Add(const AValue:TSomeClass<T>;AValue2:TSomeClass<T>): TFunc<T>;
begin
showmessage('Binary op');
exit(TObjectHandle<T>.create(T.create);
end;
procedure TForm2.FormCreate(Sender: TObject);
var a,b:TSomeClass<TDemoObject>;
c:TFunc<TDemoObject>;
begin
c:=a+b;
c:=a;
end;
constructor TObjectHandle<T>.Create(AValue: T);
begin
FValue := AValue;
end;
destructor TObjectHandle<T>.Destroy;
begin
FValue.Free;
end;
function TObjectHandle<T>.Invoke: T;
begin
Result := FValue;
end;
@!!ex (2008-11-10 21:25:00) [17]> [5] oxffff © (10.11.08 21:08)
2009? :))
У меня TDE...
oxffff (2008-11-10 21:08:00) [18]TSomeClass<T: class,constructor> = record
public
class operator Implicit(const AValue: TSomeClass<T>): T;
class operator Add(const AValue:TSomeClass<T>;AValue2:TSomeClass<T>): T;
end;
class operator TSomeClass<T>.Implicit(const AValue: TSomeClass<T>): T;
begin
showmessage('Implicit cast');
Result:=T.create;
end;
class operator TSomeClass<T>.Add(const AValue:TSomeClass<T>;AValue2:TSomeClass<T>): T;
begin
showmessage('Binary op');
exit(T.create);
end;
procedure TForm2.FormCreate(Sender: TObject);
var a,b:TSomeClass<TObject>;
c:Tobject;
begin
c:=a+b;
c:=a;
end;
@!!ex (2008-11-10 20:11:00) [19]Собственно откуда желание.
Есть два типа TVector4f и TMatrix4x4f. Оба - рекорды.
Оба типа очень активно используются.
Матрица умеет усножать себя на вектор оператором.
Сейчас понадобилось научить вектор умножать себя на матрицу. Отсюда возникла проблема:
http://www.delphimaster.ru/cgi-bin/forum.pl?n=18&id=1226325610
Вроде бы проблемы нет, если использовать класс вместо рекорда. Но!
Но вектора и матрицы разбросаны по всему коду.
Если я переделаю все на классы - придется везде бегать вставлять Create(); Free;
Отсюда:
1) Не факт что я где-то что-то не пропущу
2) Создавать и удалять явно часто используемые простые типы - это не совсем умно с точки зрения читабельности кода.
Джо (2008-11-10 20:03:00) [20]С созданием ничем не поможешь, нужно будет создавать :)
А с удалением проще — интерфейсы.