刚刚发现了一些有趣的东西:
var
Queue : TQueue <TProc>;
MyProc : TProc;
...
MyProc := Queue.Dequeue;
我想你在这里看到了什么意思。但是,编译器认为我想在Queue.Dequeue
中存储MyProc
方法(类型“对象过程”)并报告错误
E2010 Incompatible Types: 'TProc' und 'Procedure of object'
我提出的解决方法就像这样
MyProc := TProc (Pointer (Queue.Dequeue));
有更优雅的解决方案吗?
答案 0 :(得分:11)
关于名称“Dequeue”是指函数本身还是函数的返回值,存在一些语法模糊性。而且由于你正在处理一个匿名方法指针,你可以指定一个普通函数,它试图将其解释为函数赋值,而不是函数结果赋值。将它转换为指针是错误的解决方案,因为这会强制执行函数分配,这会在您尝试调用MyProc时导致各种有趣的错误。
解决问题的正确方法是消除语法歧义。在Dequeue之后放一个空括号,这样编译器就确定你调用函数而不是简单地按名称引用它,然后它就可以工作。
MyProc := Queue.Dequeue();
答案 1 :(得分:6)
正如梅森所说,Delphi语法中存在歧义。如果TFoo.Bar
是一种方法,则FooValue.Bar
表示调用TFoo.Bar
的结果或方法指针(或引用)TFoo.Bar
本身(隐含的)并不清楚FooValue的自我论证。
在梅森回答的评论中,Rob Kennedy似乎建议编译器根据所涉及的一切类型简单地解决这个问题。这并不简单;编译器已经做了很多工作来弄清楚你是想要引用方法指针值还是方法调用。当预期的接收器是方法指针(或引用或函数指针)类型时,它实际上以不同的方式解析表达式。当重载进入图片时,工作尤其明确:编译器扫描每个重载候选并检查每个参数位置中的方法指针类型,然后根据参数位置是否包含函数指针来不同地解析参数重载。然后,如果期望函数指针的重载不匹配,则编译器将解析树从函数指针更改为方法调用。重载机制本身需要确定在对参数比较执行值时要使用哪个。它非常混乱,如果我们没有让它变得更加混乱,它会很棒。
像@
或Addr()
这样的前缀样式运算符对解决这种歧义没有多大帮助,尤其是因为函数可能会返回函数指针,等等;你需要多少@
来禁止隐含(不需要()
)调用以获取正确的值?因此,当引入匿名方法时,表达式解析发生了变化:我介绍了使用()
强制调用的可能性。
您可以在此处详细了解:
http://blog.barrkel.com/2008/03/odd-corner-of-delphi-procedural.html
在这里:
http://blog.barrkel.com/2008/03/procedurally-typed-expressions-redux.html