Delphi中的procedure ... of object和ANSI C++中指向类成员函数的指针其实还是有不同的,
后者是指向类的函数的指针,实现上就是一个32bit指针或者一个vtbl的索引;
前者则是指向对象的方法的指针,实现上是一个对象指针加上一个方法指针组成的,
TMethod = record
Code, Data: Pointer;
end;
因此在标准ANSI C++中给类成员函数指针赋值必须以类为前缀,如TTest::Hello,
而在Delphi中给对象方法指针赋值必须加上对象实例,如TestObj.Hello才行
一种投机的方法是可以通过TMethod将对象方法指针重定向到一个全局函数,如
type
TFakeEvent = procedure (const strMsg: string) of object;
...
private
FTestEvent: TFakeEvent;
procedure Hello(const strMsg: string);
public
property TestEvent: TFakeEvent read FTestEvent;
end;
...
//FTestEvent := Self.Hello;
TMethod(FTestEvent).Code := @ExternalHello;
TMethod(FTestEvent).Data := nil;
...
procedure TForm1.Hello(const strMsg: string);
begin
ShowMessage('Hello '+strMsg);
end;
,,,
//注意这里传一个假参数const Null
ointer用来这里Self指针的堆栈占用空间
procedure ExternalHello(const Null: Pointer
const strMsg: string);
begin
ShowMessage('ExternalHello '+strMsg);
end;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
if Assigned(TestEvent) then
TestEvent('World');
end;
值得一提的是BCB为了兼容Delphi增加了一个__closure关键字,和of object
效果相同,但与标准c++的不同,说明如下
发信人: flier (小海->找啊找工作
), 信区: Programming
标 题: Re: 成员函数指针的问题
发信站: BBS 水木清华站 (Wed Mar 6 17:43:40 2002)
bcb里面对成员函数指针的支持实际上是有两个层面的
对应于C++标准的类成员函数指针和对应于Delphi中对象指针
我们先看看一个例子
class TTest
{
public:
void Hello(void) { ShowMessage("Hello")
}
};
如果要使用C++标准的函数指针
typedef void (TTest::*THelloFunc1)(void);
{
...
TTest t;
THelloFunc1 func1 = TTest::Hello;
(t.*func1)();
...
}
这个指针实际上是一个函数指针或者一个索引
(索引用于在vtbl中定位)
而如果使用Delphi中的对象指针则是
{
...
TTest t;
typedef void (__closure *THelloFunc2)(void);
THelloFunc2 func2;
func2 = t.Hello
//注意是对象+方法
func2()
//直接调用,因为已经绑定了对象和方法
}
注意这里的__closure关键字定义了一个函数指针
并不指向某种特定类型的类,而只是定义参数、返回值等
实际上这种指针有两个字段,分别保存指针指向的对象和对象的方法
这是在Delphi中为处理event而加入的特性,是bcb为使用vcl的扩展
和普通的C++成员函数指针不同,因此在赋值时必须加上对象才行