Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 26.05.2010, 16:08   #1
Altera
Старожил
 
Аватар для Altera
 
Регистрация: 29.01.2008
Сообщений: 2,406
По умолчанию Реалирация подсчёта ссылок на объекты класса подобно объектом интерфейса

Всем привет!
Не в том дело что мне лень следить за ссылками на мои объекты, просто интересен сам вопрос.

Меня интересует, как сделать так, чтобы объект
Код:
type
  tMyClass = class
  protected
    reffersCount: integer;
  public
    constructor create;
    destructor destroy; override;

    function incRef: integer;
    function decRef: integer;

    function someFunc(const intValue: integer): integer;
  end;

...

{ tMyClass }

constructor tMyClass.create;
begin
  reffersCount := 0;

  showMessage(format('Object created (%p)', [pointer(self)]));
end;

function tMyClass.decRef: integer;
begin
  interlockedDecrement(reffersCount);

  if reffersCount = 0 then
    destroy;
end;

destructor tMyClass.destroy;
begin
  showMessage(format('Object destroyed (%p)', [pointer(self)]));
  inherited;
end;

function tMyClass.incRef: integer;
begin
  interlockedIncrement(reffersCount);
end;

function tMyClass.someFunc(const intValue: integer): integer;
begin
  result := intValue + 1;
end;

...

{ tForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
myClass: tMyClass;

int: integer;
begin
  myClass := tMyClass.create;

  int := random(1025);
  showMessage(format('%d / %d', [int, myClass.someFunc(int)]));


  { здесь должно автоматически происходить уничтожение объекта }
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  randomize;
end;
сам бы уничтожелся, когда больше не останется ни одной ссылки, ссылающейся на него.

Может существуют некие директивы?

Последний раз редактировалось Altera; 26.05.2010 в 16:37.
Altera вне форума Ответить с цитированием
Старый 26.05.2010, 20:37   #2
alexBlack
Участник клуба
 
Регистрация: 12.10.2007
Сообщений: 1,204
По умолчанию

Судя по коду объект должен уничтожаться не при отсутствии на него ссылок, а при выходе из области видимости. В конце процедуры компилятор Delphi генерирует код для очистки интерфейсных и вариантных переменных. Вот на этом свойстве можно построить "самоуничтожающиеся" объекты. В принципе такими можно сделать объекты любого класса, но придется параллельно создавать еще и интерфейсную переменную для хранения объекта.

Например:

Код:
type
   ILocalObject = interface
      function LocalObject : TObject;
   end;

   TLocalObject = class(TInterfacedObject, ILocalObject)
   private
      FObject : TObject;
   public
      constructor Create(A:TObject);
      destructor Destroy; override;
      function LocalObject : TObject;
   end;

constructor TLocalObject.Create(A:TObject);
begin
   inherited Create;
   FObject := A;
end;

destructor TLocalObject.Destroy;
begin
   FObject.free;
   inherited Destroy;
end;

function TLocalObject.LocalObject : TObject;
begin
   result := FObject;
end;
Теперь наш класс (можно и любой другой, но чтобы проверить вызов деструктора, создадим новый):

Код:
type
   TMyObject = class
   public
      destructor Destroy; override;
   end;

destructor TMyObject.Destroy;
begin
   ShowMessage('TMyObject destroyed');
   inherited Destroy;
end;
А вот создание такого объекта:

Код:
procedure TForm12.FormCreate(Sender: TObject);
var O:ILocalObject;
    A:TMyObject;
begin
   O := TLocalObject.Create(TMyObject.Create);
   A := O.LocalObject as TMyObject;

//....
Можно наоборот, заставить сам объект создавать интерфейс:

Код:
type
   ILocalObject = interface
   end;

   TLocalObject = class(TInterfacedObject, ILocalObject)
   public
      constructor Create(var O:ILocalObject); virtual;
   end;

constructor TLocalObject.Create(var O:ILocalObject);
begin
   inherited Create;
   O := Self;
end;

type
   TMyObject = class(TLocalObject)
   public
      destructor Destroy; override;
   end;

destructor TMyObject.Destroy;
begin
   ShowMessage('TMyObject destroyed');
   inherited Destroy;
end;

procedure TForm12.FormCreate(Sender: TObject);
var O : ILocalObject;
    A : TMyObject;
begin
   A := TMyObject.CreatE(O);
С вариантными типами реализация немного сложнее, но принцип тот-же - переменная будет следить за внутренним объектом, который мы будет использовать. По моему можно даже перенаправлять все вызовы к внутреннему объекту и общаться только с вариантной переменной, но тогда теряется контроль вызовов при компиляции.
alexBlack вне форума Ответить с цитированием
Старый 26.05.2010, 23:17   #3
Altera
Старожил
 
Аватар для Altera
 
Регистрация: 29.01.2008
Сообщений: 2,406
По умолчанию

Я знаю, что с интерфейсом можно провернуть такой финт, потому и спросил. Именно так организованно самоуничтожение экземпляра объекта tCOMObject при отсутствии на него ссылок.
Об этом писал Кентум для делфи 7 и я подумал, что в новых версиях среды разработки предусмотрена какая-нить директива или маркер, говорящий компилятору о том, какие методы объекта должны вызываться при создании новой ссылки или при её уничтожении.

Ведь в объектах интерфейса так и реализовано: компилятор автоматом подставляет вызов функция _addRef при создании новой и _release при уничтожении ссылки.
Altera вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
запрос суманого подсчёта за последний месяц N@um Microsoft Office Access 5 29.04.2010 23:45
Различие абстрактного класса и интерфейса(ООП) Ruzarh PHP 0 20.11.2009 15:29
Массив ссылок на функции класса therom Общие вопросы C/C++ 0 30.09.2008 15:59
Формула в Экселе для подсчёта стоимости Oxidous Microsoft Office Excel 13 31.08.2007 13:13