![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Интерфейсы [D6, Win2k]
Vlad2 © (2002-07-23 11:33:00)Проясните, пожалуйста, ситуацию:
1. Существуют два объекта (o1, o2), - наследники TForm;
2. Оба они реализуют интерфейс IanyInterface;
3. В тексте модуля создается интерфейсная ссылка ai: IanyInterface;
ai := o1.Create или ai := o2.Create
4. При выполнении ai := nil; деструкторы объектов o1 или o2
не вызываются. Поэтому, перед созданием интерфейсной ссылки
приходится определять тип созданного объекта и вызывать
o1.Free или o2.Free
Непонятно, - почему не вызываются деструкторы при ai := nil ?
С уважением, Vlad2.
Vlad2 (2002-07-24 06:46:00) [1]>vuk
Прошу извинить за паузу.
Мне кажется, все работает так: интерфейсные ссылки вначале выполняют _Release, а затем Destroy (при необходимости); а объектные ссылки сразу выполняют Destroy (например, при удалении владельца). Т.е. объект может быть удален разными способами, и в каждом нужно соблюсти корректность. А если добавить в деструктор владельца вызов _Release ?
vuk (2002-07-23 15:37:00) [2]Нет не это имелось в виду. Предположим, у Вас есть компонент реализующий интерфейс (с учетом подсчета ссылок) и Вы создаете компонент.
При этом возможны следующие ситуации:
1. Вы запрашиваете интерфейс, работаете с ним, а при выходе из процедуры, где это все делается, Ваш компонент будет автоматически уничтожен (что, скорее всего, Вам не нужно), поскольку счетчик ссылок будет равен 0.
2. Вы где-то запрашиваете у этого компонента интерфейс и сохраняете его в переменной. После чего в каком-то другом месте пытаетесь удалить владельца компонента. Естественно, получите исключение, поскольку имеются ссылки на интерфейс...
Vlad2 (2002-07-23 15:03:00) [3]>vuk
Если я правильно понял, может возникнуть ситуация, когда владелец выполнил Destroy объекта, а реализованный в нем метод
_Release не выполнился ?
vuk (2002-07-23 13:39:00) [4]Если Вы реализуете интерфейсы в наследниках TComponent, то нужно быть осторожным с подсчетом ссылок, т.к. в случае с компонентами временем жизни объекта обычно управляет не он сам, а его владелец, поэтому возможны неприятности...
Vlad2 (2002-07-23 12:20:00) [5]Ребята ! Всем спасибо. Очень-очень и все все все.
Digitman (2002-07-23 12:20:00) [6]>Skier
Точно !
Я и забыл совсем, что TComponent их реализует) Поэтому и компилятор "молчит"
Skier (2002-07-23 12:13:00) [7]>Vlad2
В догонку :
Код можно взять из
TInterfacedObject._AddRef
и TInterfacedObject._Release
Skier (2002-07-23 12:11:00) [8]>Vlad2
Bingo !
Vlad2 (2002-07-23 12:10:00) [9]Что - то проясняется. Спасибо. Но
to Skier: я должен реализовать методы
_AddRef и
_Release
в своих классах o1 и o2 ?
Skier (2002-07-23 12:08:00) [10]>Digitman
У него "подсчёт ссылок" (хотя там ничего не считается)
уходит, видимо, сюда :
function TComponent._AddRef: Integer; stdcall;
function TComponent._Release: Integer; stdcall;
Digitman (2002-07-23 12:06:00) [11]<Skyer>, извини, последняя реплика не по адресу - она для <Vlad2>
Digitman (2002-07-23 12:03:00) [12]>Skier
Да , в общем-то, необязательно, согласен ...
Но для общего случая, когда объект может реализовать более одного интерфейса, это гораздо наглядней, согласись
>Skier
Деструктор объекта, в общем случае, следует вызывать в реализации интерфейсного метода IUnknown._Release (при достижении RefCount = 0, сч-к ссылок же инкрементируется в теле IUnknown._AddRef). То, что тебе удалось скомпилировать код модуля, говорит о том, что какую-то реализацию этого метода ты все же выполнил. Но вот отсутствие автовызова деструктора, скорее всего, говорит именно о том, что нигде в обязательной реализации методов интерфейса IUnknown подобный код не присутствует у тебя
Skier (2002-07-23 11:46:00) [13]>Digitman
as IAnyInterface а это зачем ?
Digitman (2002-07-23 11:43:00) [14]ai := o1.Create as IAnyInterface;
ai := nil;
Skier (2002-07-23 11:37:00) [15]>Vlad2
Потому что не считаются ссылки.
Загляни в методы класса-предка
function _AddRef: Integer; stdcall; и
function _Release: Integer; stdcall;