delphi class object interface free

delphi - ¿Cómo puede la interfaz implementada la clase gratuita?



class object (2)

Tengo un pequeño problema. Como el título dice que quiero liberar un objeto cuya clase implemente una interfaz, sin embargo, aparece el error "operación de puntero no válida" .

Mi interfaz:

Interface Type // An interface definition IMessageEvents = Interface(IInterface) [''{BD27EFC6-CC9A-437A-A8B8-16F722518836}''] Procedure messageReceived(messageData: String); End; Implementation

Mi clase:

Type TChatManager = Class(TInterfacedObject, IMessageEvents) Private Protected Procedure messageReceived(messageData: String); Overload; Public Constructor Create; Overload; Destructor Destroy; Override; Procedure connect; Procedure disconnect; End; Implementation Constructor TChatManager.Create; Begin { ....... } End; Procedure TChatManager.connect; Begin { ....... } End; Procedure TChatManager.disconnect; Begin { ....... } End; Procedure TChatManager.messageReceived(messageData: String); Begin { ....... } End; Destructor TChatManager.Destroy; Begin Inherited Destroy; End;

Mi código:

self.chatMng := TChatManager.Create; self.chatMng.Free;

¿Alguien puede decirme lo que estoy haciendo mal? Gracias por adelantado.


Parece que chatMng es de tipo TChatManager . Esto se puede deducir por el hecho de que asigne TChatManager.Create a él y llame a Free en él.

Sin embargo, TChatManager deriva de TInterfacedObject . Eso significa que su duración está controlada por las referencias que se llevan a sus interfaces. Cuando se lanza la referencia final, el objeto se destruye.

La regla general es que si deriva de TInterfacedObject , nunca debe tomar una referencia al objeto que no sea a través de una variable de interfaz.

Pasos para corregir tu código:

  1. Cambie chatMng por ser de tipo IMessageEvents .
  2. Elimine la llamada a chatMng.Free que el compilador se opondrá en cualquier caso.

No debe mostrarnos todo el código ... porque lo que muestra no debe causar un GPF ... puedes crear un TInterfacedObject y liberarlo ... si no obtienes una referencia ... pero si obtienes una referencia, ya no estás a cargo de liberarla ...

Aquí está la interfaz

unit Unit3; Interface uses Classes, SysUtils; Type // An interface definition IMessageEvents = Interface(IInterface) [''{BD27EFC6-CC9A-437A-A8B8-16F722518836}''] Procedure messageReceived(messageData: String); End; Type TChatManager = Class(TInterfacedObject, IMessageEvents) Private FStrings: TStrings; Protected Procedure messageReceived(messageData: String); Overload; procedure UpdateStatus(aString: string); Public Constructor Create(aStrings: TStrings); Destructor Destroy; Override; Procedure connect; Procedure disconnect; End; Implementation Constructor TChatManager.Create(aStrings: TStrings); Begin { ....... } FStrings := aStrings; UpdateStatus(''Created''); Connect; End; Procedure TChatManager.connect; Begin { ....... } UpdateStatus(''Connected''); End; Procedure TChatManager.disconnect; Begin { ....... } UpdateStatus(''DisConnected''); End; Procedure TChatManager.messageReceived(messageData: String); Begin { ....... } UpdateStatus(''Message Received''); UpdateStatus(messageData); End; procedure TChatManager.UpdateStatus(aString: string); begin FStrings.Add(aString); FStrings.Add(''RefCount: ''+ IntToStr(Self.RefCount)); end; Destructor TChatManager.Destroy; Begin Disconnect; UpdateStatus(''Destroyed''); Inherited Destroy; End; end.

Aquí está la forma

unit Unit2; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, unit3, StdCtrls; type TForm2 = class(TForm) Button1: TButton; Memo1: TMemo; Button2: TButton; Button3: TButton; Button4: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); private { Private declarations } chatMng: TChatManager; iChatMng: IMessageEvents; public { Public declarations } end; var Form2: TForm2; implementation {$R *.dfm} type THackManager= class(TChatManager); procedure TForm2.Button1Click(Sender: TObject); begin chatMng := TChatManager.Create(Memo1.Lines); THackManager(ChatMng).messageReceived(''Hello World from Button1''); chatMng.Free; end; procedure TForm2.Button2Click(Sender: TObject); begin iChatMng := TChatManager.Create(Memo1.Lines); iChatMng.messageReceived(''Hello World from Button2''); iChatMng := nil; end; procedure TForm2.Button3Click(Sender: TObject); begin ChatMng := TChatManager.Create(Memo1.Lines); (ChatMng as IMessageEvents).messageReceived(''Hello World from Button3''); //you can''t call ChatMng...it''s gone bye bye... //ChatMng.Free; //this will cause a GPF if you call free end; procedure TForm2.Button4Click(Sender: TObject); var a_IChatMng: IMessageEvents; begin ChatMng := TChatManager.Create(Memo1.Lines); a_IChatMng := chatMng; (ChatMng as IMessageEvents).messageReceived(''Hello World from Button4''); a_IChatMng.messageReceived(''Hello World again from Button4''); //ChatMng.Free; //this will cause a GPF if you call free end; end.

Aquí está el dfm

object Form2: TForm2 Left = 326 Top = 94 Caption = ''Form2'' ClientHeight = 292 ClientWidth = 581 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = ''Tahoma'' Font.Style = [] OldCreateOrder = False PixelsPerInch = 96 TextHeight = 13 object Button1: TButton Left = 40 Top = 200 Width = 75 Height = 25 Caption = ''Button1'' TabOrder = 0 OnClick = Button1Click end object Memo1: TMemo Left = 40 Top = 32 Width = 411 Height = 129 TabOrder = 1 end object Button2: TButton Left = 160 Top = 200 Width = 75 Height = 25 Caption = ''Button2'' TabOrder = 2 OnClick = Button2Click end object Button3: TButton Left = 272 Top = 200 Width = 75 Height = 25 Caption = ''Button3'' TabOrder = 3 OnClick = Button3Click end object Button4: TButton Left = 376 Top = 200 Width = 75 Height = 25 Caption = ''Button4'' TabOrder = 4 OnClick = Button4Click end end