Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.01.13;
Скачать: CL | DM;

Вниз

"Устаревший стиль объекта"   Найти похожие ветки 

 
Key   (2007-10-13 09:56) [0]

Уважаемые мастера

Работаю с нек. компонентом. В нем приходится работать с записями. Сообщаешь ему размер этой записи, он сам ее путем GetMem() у себя формирует, куда надо вставляет и когда надо, возвращает на нее указатель. При разрушении - вызывает FreeMem()

Также у этого хитрого компонента предусмотрены события InitItem и FreeItem, выполняющие функции конструктора и деструктора соответственно. Не знаю, почему так, не спрашивайте. :)

Работает нормально, но после работы с классами очень неуютно чувствуешь себя с record. Ни тебе метод написать, ни свойство. Появилась идея заменить record на .... "устаревший" object. Что интересно, работает нормально тоже. И даже свойство вызывается. И память чистится правильно. Фактически это аналог экземпляра класса в C++ (не указателя на него, а расположенного, скажем, в стеке). Разве что конструкторы и деструкторы не вызываются :(

Но Delphi меня начало предупреждать, что мол
"Unsafe type "TXSDTreeRec: old style object""

Значит ли это, что пользоваться object нельзя потому, что их поддержка в следующих версиях отсутствует? Или работа их не гарантируется? Или еще какие-то подводные камни?

Спасибо.


 
Leonid Troyanovsky ©   (2007-10-13 15:41) [1]


> Key   (13.10.07 09:56)  

> Работает нормально, но после работы с классами очень неуютно
> чувствуешь себя с record. Ни тебе метод написать, ни свойство.
>  Появилась идея заменить record на .... "устаревший" object.

Напиши лучше свой компонент для управления чужим.
Например, ссылки на распределенные записи будет
держать TList и т.д.

Не забудь про Notification; override для того, чтобы
всегда иметь валидную ссылку на чужой.

--
Regards, LVT.


 
просто так   (2007-10-15 13:16) [2]

>>Работает нормально
Пока у обжекта нет виртуальных методов он не отличается от рЕкорда
>>object нельзя потому, что их поддержка в следующих версиях отсутствует?
а вот это наврятли


 
Anatoly Podgoretsky ©   (2007-10-15 14:10) [3]


> а вот это наврятли

А вот это запросто, Борланд предупреждал.


 
Sapersky   (2007-10-15 20:23) [4]

Наследование в сочетании с managed-типами (aka типы с управляемым временем жизни - длинные строки, дин. массивы, варианты, интерфейсы) может привести к проблемам:

TFirstObj = object
 s : String;
end;

TSecondObj = object (TFirstObj)
// ...
end;

TSecondObj ничего не знает об s : String; и не сможет её корректно инициализировать/финализировать. Хотя проблема не фатальная - например, в библиотеке KOL она решена созданием объектов через New (при этом поля заполняются нулями) и уничтожением всех строк вручную в деструкторе (s := "").
Прискорбно жаль, что Борланд/КодГир ничего не пишут в хелпе по этому поводу (кроме their use is not recommended).

М-да, только сейчас сообразил: если ваш супер-компонент выделяет память через GetMem, ему managed-типы вообще противопоказаны. Ну разве что обрабатывать их вручную в InitItem и FreeItem - но какие они после этого managed.


 
просто так   (2007-10-15 21:32) [5]

>>TSecondObj ничего не знает об s : String
с чего это вдруг ничего не знает? на то оно и наследование чтоб знать))


 
DVM ©   (2007-10-15 22:41) [6]

у меня в BDS2006 один модуль как то не хотел компилироваться, потому, что там вместо class было объявлено object. Просто не компилировался и все. Писал внутренняя ошибка и курсор вставал на завершающую точку в модуле. Пришлось поменять. А в предыдущих версиях все нормально компилировалось.


 
Sapersky   (2007-10-16 02:46) [7]

с чего это вдруг ничего не знает?

В основном потому, что на момент создания object managed-типов ещё не было в природе. А потом - то ли было в принципе невозможно, то ли не захотели менять внутреннюю структуру object, чтобы не поломать обратную совместимость.
Можете проверить:

Var fObj : TFirstObj;
     sObj : TSecondObj;
fObj.s := ... ;// всё нормально
sObj.s := ... ;// AV


 
просто так   (2007-10-16 07:10) [8]

>>у меня в BDS2006 один модуль как то не хотел компилироваться, потому, что там вместо class было объявлено object.
думаю причины были совсем не в object. с ними всё ок в BDS2006.
>>sObj.s := ... ;// AV
врешь и не краснеешь)). хотя может дело в коментарии
fObj.s := ... ;// всё нормально
sObj.s := ... ;// всё нормально
так всё работает)) может ты использовал виртуальные методы до вызова конструктора?


 
просто так   (2007-10-16 07:13) [9]

>>Sapersky
program Project1;
{$APPTYPE CONSOLE}
uses
 SysUtils;
type
TFirstObj = object
s : String;
end;
TSecondObj = object (TFirstObj)
end;
Var fObj : TFirstObj;
   sObj : TSecondObj;
begin
fObj.s := "1" ;// всё нормально
sObj.s := "2" ;// всё нормально
end.
Проверь еще раз


 
просто так   (2007-10-16 07:36) [10]

>>TSecondObj ничего не знает об s : String; и не сможет её корректно инициализировать/финализировать. Хотя проблема не фатальная - например, в библиотеке KOL она решена созданием объектов через New (при этом поля заполняются нулями) и уничтожением всех строк вручную в деструкторе (s := "").

так сделано совсем не по этому. для динамически созданых рекордов/обжектов присваивание стрингов/дин.массивов := "", обязательно иначе будут мемлики. для переменных объявленных в секции var за нас это сделает компилятор


 
Sapersky   (2007-10-16 09:25) [11]

AV будет с локальными переменными.
С глобальными, впрочем, тоже не всё гладко - будет утечка.

для динамически созданых рекордов/обжектов присваивание стрингов/дин.массивов := "", обязательно

Если через New/Dispose(Free), то не обязательно, во всяком случае для TFirstObj. Если через GetMem/FreeMem - то да.


 
просто так   (2007-10-16 09:34) [12]

>>AV будет с локальными переменными. С глобальными, впрочем, тоже не всё гладко - будет утечка.

AV не будет. если конечно не обращаться локальному к объекту после его выхода из зоны видимости. но это другая песня.
Поясни пожалуйста по утечке


 
Sapersky   (2007-10-16 09:59) [13]

Я же писал: TSecondObj ничего не знает об s : String; и не сможет её корректно инициализировать/финализировать.
Т.е. в локальной переменной sObj.s при входе в область видимости будет мусор. При попытке присвоить ей что-нибудь компилятор попытается "освободить" старую "строку", со всеми печальными вытекающими.
В глобальной будет nil, поэтому обойдётся без AV. Но корректно освободить память компилятор не сможет. Потому как информация о managed-типах у объектов и классов хранится только для текущего уровня иерархии, но если по классу легко получить его предка, то как это сделать для объекта - даже матёрые приКОЛисты не смогли додуматься, насколько я помню. А компилятор, в принципе, использует те же (ну или почти те же) средства.


 
просто так   (2007-10-16 10:06) [14]

Специально токачто попробовал вышеизложенный пример завернутый в процедуру. всё работает. если переменная объявлена в var секции она инициализируется корректно и TSecondObj прекрасно знает об s. проблемы могут возникнуть только при динамическом создании, для их решения можно завести отдельный конструктор который будет делать принудительное pointer(s):=nil;


 
Sapersky   (2007-10-16 10:25) [15]

Какой Delphi? У меня в 5-м AV.
Код полностью:

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

 TFirstObj = object
   s : String;
 end;

 TSecondObj = object (TFirstObj)
 end;

var
 Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
Var fObj : TFirstObj;
   sObj : TSecondObj;
begin
fObj.s := "1";
sObj.s := "2";
end;

end.


 
DVM ©   (2007-10-16 11:53) [16]


> просто так   (16.10.07 07:10) [8]
> >>у меня в BDS2006 один модуль как то не хотел компилироваться,
>  потому, что там вместо class было объявлено object.
> думаю причины были совсем не в object. с ними всё ок в BDS2006.
>

Может и не в object, но скомпилировался, только после замены на class.

Вот он кстати (модуль не мой).  http://dvmuratov.narod.ru/CpuInfo.pas

Вот в таком виде он не компилируется.


 
просто так   (2007-10-16 14:06) [17]

>>Sapersky
Убедил. у меня AV нету но в s мусор...
я проверял в консольном приложении, в s всё ок, но при добавлении полей в TFirstObj тоже появился мусор. сыплюголову пеплом)))
делаю большой проект на обжектах, ниразу с этим не сталкивался, т.к. не использую локальные сложные переменные



Страницы: 1 вся ветка

Текущий архив: 2008.01.13;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.016 c
15-1197264407
Gydvin
2007-12-10 08:26
2008.01.13
windows server 2003 и русские названия папок


2-1197642802
destrs
2007-12-14 17:33
2008.01.13
dll, что не так делаю...


1-1192541756
Bozzy
2007-10-16 17:35
2008.01.13
Проблема с ресурсами


2-1197824270
tracert's
2007-12-16 19:57
2008.01.13
Определение максимального размера фонта


15-1196853263
alshtam
2007-12-05 14:14
2008.01.13
как висту снести???