![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Добавление объектов в ComboBox (Tobject(string)) [D7, WinXP]
Nike85 © (2007-11-02 15:25:00)Здравствуйте!
Не могу понять, чем вызвана следующая проблема:
читаю из бд данные - имя записи (name) и строковое представление идентификатора (anrec), добавляю их в расположенный на форме комбобокс (имя - как строку, идентификатор - в список объектов). Однако при дальнейшем выводе идентификатора - выходит абракадабра (пустое сообщение - такое ощущение, что где-то утечка памяти).
Код ниже:
//Чтение данных:
//s1,s2: string;
while not tempQuery1.Eof do
begin
s1:=tempQuery1.FieldByName('name').AsString;
s2:=tempQuery1.FieldByName('anrec').AsString;
ShowMessage(s2);
cmbStatus.Items.AddObject(s1,Tobject(s2));
TempQuery1.Next;
end;
//Вывод данных:
ShowMessage(string(cmbStatus.Items.Objects[cmbStatus.ItemIndex]));
Юрий Зотов (2007-11-03 23:50:00) [1]> Nike85 (02.11.07 15:50) [9]
В Delphi строка - это не объект. Это Pointer на Record специального (compiler-magic) типа. Структура такая:
-8: Счетчик ссылок
-4: Длина тела в байтах
0: Тело строки, заканчивающееся нулем (ASCIIZ)
Хранятся строки в динамической памяти, а рулит всей этой фигней компилятор. В частности, он же вставляет код изменения счетчика ссылок и код освобождения памяти, если счетчик ссылок стал нулевым.
Но компилятор - не человек, и даже не ИИ. Поэтому он не понимает, что при выполнении кода
TStrings.AddObject(s1, TObject(s2)
счетчик ссылок в строке s2 должен быть увеличен. Он его и не увеличивает. Поэтому, как только переменная s2 получает новое значение, ее старое значение уничтожается и Objects[i] начинает ссылаться в никуда.
Kolan (2007-11-02 17:22:00) [2]
TMyObject = class
private
FName: string;
FAnrec: string; //ХЗ что есть anrec
public
constructor Create(Name, Anrec: string);
end;
//Чтение данных:
//s1,s2: string;
while not tempQuery1.Eof do
begin
with tempQuery1 do
cmbStatus.Items.AddObject(s1, TMyObject.Create(FieldByName('name').AsString,
FieldByName('anrec').AsString));
TempQuery1.Next;
end;
Написание савойств, кода конструктора дом. задание.
Kolan (2007-11-02 17:18:00) [3]> если при хранении в комбобоксе
Дело в том что комбо это элемент интерфейса и он не очень то пригоден для хронения данных.
В любом случае даже при использовании комбо, лучьше матеарелизовывать объект(с понятным именем и внятными полями) и сохронять его
clickmaker (2007-11-02 16:19:00) [4]
> [15] Nike85 (02.11.07 16:04)
> сможет ли Object удалить себя, вызывая Free, даже если обжект
> представлен Pchar-ом?
PChar - это PChar, а обжект - это обжект
Первый - указатель на область памяти, где находится просто массив байтов.
Вотрой - тоже по сути указатель, но по этому адресу живет объект некоего классасо свойствами и методами.
Почувствуйте разницу
Anatoly Podgoretsky (2007-11-02 16:10:00) [5]> Nike85 (02.11.2007 15:56:12) [12]
> А что будет если вызывать Objects[i].Free?
Ой не делай этого, будет больно.
Anatoly Podgoretsky (2007-11-02 16:10:00) [6]> Reindeer Moss Eater (02.11.2007 15:52:11) [11]
Как чем, с помощью справки конечно, бить ею по голове до полного просветления.
Anatoly Podgoretsky (2007-11-02 16:09:00) [7]> Nike85 (02.11.2007 15:36:04) [4]
Глобальную конечно завести можно, она удаляться не будет, но и все объекты будут одинаковы.
Nike85 (2007-11-02 16:08:00) [8]To Kolan © :
А зачем я буду синхронизировать комбо с внешним списком, если при хранении в комбобоксе данные всегда будут синхронизованы (даже если я буду пересортировывать строки комбо, то автоматом и будут пересортировываться объекты, с ними связанные (а может и не будут :))). Да и внешний список - это еще одна явно объявленная переменная, модуль читать не удобно. Не, мне больше вариант с хранением в комбо нравится
Nike85 (2007-11-02 16:04:00) [9]сможет ли Object удалить себя, вызывая Free, даже если обжект представлен Pchar-ом? Конечно, если использовать приведение к пчару, то можно удалять и через strdispose. Только вот вопрос теперь у меня такой, если вызвать Objects[i].Free, хватит ли сил объекту Тобжект корректно удалить себя, даже если внутри него инкапсулирован Пчар, или допустим объект Tform. В каком случае будет выше производительность? - если через strDispose, или через метод Tobject?
Kolan (2007-11-02 16:00:00) [10]Вставлю своё имхо. Данные не надо хронить в ComboBox'е или пользуй DB Aware контрол
или (как сделал бы я) метериализуй объекты из БД и хрони их в отдельном списке. При надобности синхронизируй список с комбо и наоборот
Reindeer Moss Eater (2007-11-02 15:58:00) [11]А попробуй.
Зачем Free, если никто Create не делал?
Nike85 (2007-11-02 15:56:00) [12]Возможно вот так?
for i:=cmbStatus.Items.Count-1 downto 0 do
StrDispose(Pchar(cmbStatus.Items.Objects[i]));
cmbStatus.Clear;
А что будет если вызывать Objects[i].Free?
Reindeer Moss Eater (2007-11-02 15:52:00) [13]Ну подумай, если память распределялась с помощью StrNew, то чем же надо её освобождать?
Nike85 (2007-11-02 15:51:00) [14]только не даунту 1, а 0 :))
Nike85 (2007-11-02 15:50:00) [15]To Юрий Зотов © :
строка - не объект, это не си шарп. Или нет??
To Reindeer Moss Eater ©
Ок, че я где-то подобное уже видел. Создать объект новый надо было. Спасибо, кажется так заработает. Сейчас проверю. А освобождать объекты надо как, например при очистке списка перед его новым заполнением?
for i:=cmbStatus.Items.Count-1 downto 1 do
cmbStatus.Items.Objects[i].Free;
Правильно я понимаю или нет?
Reindeer Moss Eater (2007-11-02 15:41:00) [16]cmbStatus.Items.AddObject(s1,TObject(StrNew(PChar(s2))));
Nike85 (2007-11-02 15:40:00) [17]To Reindeer Moss Eater © :
Это как, можно по-подробнее? Pchar-ом пользоваться? можно код? Объясните дураку
To Kolan © :
Дблукап не хотелось бы использовать. Да и тут уже дело принципа - как заставить комбобокс хранить свои объекты :))
Юрий Зотов (2007-11-02 15:39:00) [18]> Nike85 (02.11.07 15:25)
Разве строка - это объект?
Строка имеет управляемое время жизни и как только счетчик ссылок на нее обнуляется, занимаемая ею память автоматически освобождается (и, соответственно, ссылки на нее становятся недействительными). У Вас это происходит со строкой s2 на каждом новом витке цикла.
Используйте Names и Values.
Reindeer Moss Eater (2007-11-02 15:37:00) [19]Переменные не нужны. Нужно явно распределять память под строки
Nike85 (2007-11-02 15:36:00) [20]Как сделать "вечно живущие" объекты? не заводить же для это глобальные переменные? Я пока делаю так - для каждого комбобокса - их уже штуки 4 у меня на форме,я сделал объекты Tstringlist. Но это мне кажется как-то коряво