Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从Delphi中的子类获取基类中方法的指针?_Delphi - Fatal编程技术网

如何从Delphi中的子类获取基类中方法的指针?

如何从Delphi中的子类获取基类中方法的指针?,delphi,Delphi,下面是我的代码示例: type TMyBaseClass = class public procedure SomeProc; virtual; end; TMyChildClass = class(TMyBaseClass) public procedure SomeProc; override; end; var SomeDelegate: procedure of object; procedure TMyBaseClass.SomePro

下面是我的代码示例:

type
  TMyBaseClass = class
  public
    procedure SomeProc; virtual;
  end;

  TMyChildClass = class(TMyBaseClass)
  public
    procedure SomeProc; override;
  end;

var
  SomeDelegate: procedure of object;

procedure TMyBaseClass.SomeProc;
begin
  ShowMessage('Base proc');
end;

procedure TMyChildClass.SomeProc;
begin
  ShowMessage('Child proc');
  // here i want to get a pointer to TMyBaseClass.SomeProc (NOT IN THIS CLASS!):
  SomeDelegate := SomeProc;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TMyChildClass.Create do
  try
    // there will be "Child proc" message:
    SomeProc;
  finally
    Free;
  end;
  // there i want to get "Base proc" message, but i get "Child proc" again
  // (but it is destroyed anyway, how coud it be?):
  SomeDelegate;
end;
我知道的一个方法是:

procedure TMyChildClass.BaseSomeProc;
begin
  inherited SomeProc;
end;


procedure TMyChildClass.SomeProc;
begin
  ShowMessage('Child proc');
  SomeDelegate := BaseSomeProc;
end;
第二个是将
SomeProc
声明从
override
更改为
重新引入

 TMyChildClass = class(TMyBaseClass)
 public
    procedure SomeProc; reintroduce;
 end;
然后将
self
转换为
TMyBaseClass
(不要使用
as
cast):


还要注意的是,您的代码将导致访问冲突,因为您对已释放的对象调用了
SomeDelegate

添加类型声明和一些类型转换是有效的,但会附带一些警告说明

正如您自己所提到的,在实例被释放后调用somedelegate并不正确。这是因为您的SomeProc方法不使用任何实例变量,它所做的只是调用ShowMessage

如果您向调用中添加了任何实例变量,如果内存没有被重新分配,您甚至可能会侥幸逃脱。这将是一个等待发生的AV

底线:

  • 不要取消已销毁对象的方法
  • 从类的实例中设置一个在类的生存期内仍然存在的全局变量被认为是不好的设计
  • 在理想的设计中,除了通过调用继承的方法外,不需要子类以任何方式将调用还原到祖先的方法
代码更改

...
type
  TSomeDelegate = procedure of object;

var
  SomeDelegate: TSomeDelegate;

...

procedure TMyChildClass.SomeProc;
var
  method: TMethod;
begin
  ShowMessage('Child proc');
  // here i want to get a pointer to TMyBaseClass.SomeProc (NOT IN THIS CLASS!):
  method.Code :=  @TMyBaseClass.SomeProc;
  method.Data := Self;
  SomeDelegate := TSomeDelegate(method);
end;

谢谢您的第一种方法正是我想要的=)请注意Michal Niklas关于访问违规的说法。你仍然会得到一个,即使是“继承的”。这是因为您不能有一个指向类的方法的指针(除非它声明为“类过程”),而只能指向对象的方法。调用Free()时,对象将被销毁,对它的任何引用(包括包含对其函数引用的SomeDelegate)都不再有效。使用我的Turbo Delphi编写代码时,我遇到访问冲突异常。
...
type
  TSomeDelegate = procedure of object;

var
  SomeDelegate: TSomeDelegate;

...

procedure TMyChildClass.SomeProc;
var
  method: TMethod;
begin
  ShowMessage('Child proc');
  // here i want to get a pointer to TMyBaseClass.SomeProc (NOT IN THIS CLASS!):
  method.Code :=  @TMyBaseClass.SomeProc;
  method.Data := Self;
  SomeDelegate := TSomeDelegate(method);
end;