免费接口如何实现类?

时间:2013-12-16 18:59:35

标签: delphi class object interface free

我有点问题。正如标题所说我想发布一个类实现接口的对象,但是我得到一个错误“无效指针操作”

我的界面:

Interface

Type
  // An interface definition
  IMessageEvents = Interface(IInterface)
    ['{BD27EFC6-CC9A-437A-A8B8-16F722518836}']

    Procedure messageReceived(messageData: String);
  End;

Implementation

我的班级:

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;

我的代码:

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

谁能告诉我我做错了什么?提前谢谢。

2 个答案:

答案 0 :(得分:2)

chatMng似乎是TChatManager类型。这可以通过向您分配TChatManager.Create并在其上调用Free来推断。

但是,TChatManager来自TInterfacedObject。这意味着它的生命周期由引入其接口的引用控制。释放最终引用时,对象将被销毁。

经验法则是,如果你从TInterfacedObject派生,那么除了通过接口变量之外,你绝不能引用对象。

纠正代码的步骤:

  1. chatMng更改为IMessageEvents类型。
  2. 删除对编译器在任何情况下都会反对的chatMng.Free的调用。

答案 1 :(得分:1)

他一定不能向我们展示所有的代码...因为他所展示的内容不应该导致GPF ...你可以创建一个TInterfacedObject并释放它...如果你没有得到它的引用.. .but如果你得到一个参考,你不再负责释放它......

这是界面

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.

这是表格

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.

这是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