高难度问题,可不是你想的那么简单:如何强行指定调用重载函数中的某一个? (200分)

L

lyco

Unregistered / Unconfirmed
GUEST, unregistred user!
这个问题有点怪,因为为一般重载函数的调用是有参数指定的,所以没有必要
显式指定.
但是,有下面的情况,函数和类型定义如下:
type
FuncPointer1 = procedure(X: Integer)

FuncPointer2 = procedure(X, Y: Integer)


procedure Test(X: Integer)
overload

procedure Test(X, Y: Integer)
overload

procedure FuncAssign(FP1: FuncPointer1)
overload

procedure FuncAssign(FP1: FuncPointer2)
overload


这时,如果我调用:
FuncAssign(Test)

在编译时就会出现"Ambiguous overloaded call"的错误;
如果我不想改变几个重载函数的名字,也就是说,如果我想显式指定
我要的调用的过程,那么我的函数调用语法应该怎么写呢?

 
L

lujr

Unregistered / Unconfirmed
GUEST, unregistred user!
加上参数试试,没参数它怎么知道你调哪一个?

 
L

lyco

Unregistered / Unconfirmed
GUEST, unregistred user!
Lujr, 如果你把把正确的调用方法写出来,我的200分就给你!
 
W

wbcp2000

Unregistered / Unconfirmed
GUEST, unregistred user!
等待....
 
Q

qiya

Unregistered / Unconfirmed
GUEST, unregistred user!
搞了半天 没想到,关键在于如何取得2个Test的地址!我想过用Label可是不行!:(!
 
Y

yhaochuan

Unregistered / Unconfirmed
GUEST, unregistred user!
有你这么用overload蹂躏delphi的吗。
什么情况要用到这么诡异的方法,可以说说吗?
 
D

djflying

Unregistered / Unconfirmed
GUEST, unregistred user!
这个问题真有难度!
关注!
 
W

westboy2000

Unregistered / Unconfirmed
GUEST, unregistred user!
难度不小,偶已经试了一早上了,还没搞定![:(!]
 
C

cgzhang

Unregistered / Unconfirmed
GUEST, unregistred user!
这样:
procedure TForm1.Button1Click(Sender: TObject);
var
f1:funcpointer1;
begin
funcassign(f1);
end;
顺便说一句,这个程序除了炫耀技巧外毫无用处
 
W

westboy2000

Unregistered / Unconfirmed
GUEST, unregistred user!
终于搞定了,调用FuncAssign时要这样写:
procedure TForm1.Button1Click(Sender: TObject);
var
FP:FuncPointer1;
begin
FP:=Test;
FuncAssign(FP);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
FP:FuncPointer2;
begin
FP:=Test;
FuncAssign(FP);
end;
就可以强行指定调用的过程了。
上面的兄弟cgzhang给了不少启示,不过必须要加上一句 FP:=Test
来指定一下,
否则程序运行会报错的,因为程序找不到FP1到底是什么,所以要强制指定一下。
 
D

darkiss

Unregistered / Unconfirmed
GUEST, unregistred user!
这样就可以了.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

FuncPointer1 = procedure(X: Integer);
FuncPointer2 = procedure(X, Y: Integer);

procedure Test(X: Integer)
overload;
procedure Test(X, Y: Integer)
overload;
procedure FuncAssign(FP1: FuncPointer1)
overload;
procedure FuncAssign(FP1: FuncPointer2)
overload;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure Test(X: Integer);
begin
showmessage('1')
end
procedure Test(X, Y: Integer);
begin
showmessage('2')
end
procedure FuncAssign(FP1: FuncPointer1);
begin
showmessage('3')
end
procedure FuncAssign(FP1: FuncPointer2);
begin
showmessage('4')
end
////////////////////////////////// here /////////////////////////
procedure TForm1.Button1Click(Sender: TObject);
begin
funcAssign(FuncPointer1(@test))
//或者是funcAssign(FuncPointer2(@test))
end;

end.

需要制定参数类型,动态束定的时候,在你这种情况,编译器是分辨不出来你想怎样做的.
 
D

darkiss

Unregistered / Unconfirmed
GUEST, unregistred user!
加一个局部变量是没有必要的,你应该弄清楚这样的原因.To think like the compiler
 
Q

qiya

Unregistered / Unconfirmed
GUEST, unregistred user!
>>westboy2000
>>darkiss
你们用的是DELPHI5还是6?
 
D

darkiss

Unregistered / Unconfirmed
GUEST, unregistred user!
我用的是6.怎么?
 
Q

qiya

Unregistered / Unconfirmed
GUEST, unregistred user!
5可是通不过的呀!
 
D

darkiss

Unregistered / Unconfirmed
GUEST, unregistred user!
ok.看来我要装个5了.是不是还要装个1呢??这个项目完了以后再说.呵呵.
 
M

marknew

Unregistered / Unconfirmed
GUEST, unregistred user!
westboy2000的是不对的,你真的试过吗?FP:=Test;不能这样。比较好的方法应该是
这样的:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
FuncPointer1=procedure(X: Integer) of object
FuncPointer2=procedure(X, Y: Integer) of object;
ClassA=class
private
procedure Test(X: Integer);overload;
procedure Test(X, Y: Integer);overload;
procedure FuncAssign(FP1:FuncPointer1;x:integer)
overload;
procedure FuncAssign(FP1:FuncPointer2;x,y:integer)
overload;
procedure testA(x,y:integer);
end;

var
Form1: TForm1;
implementation
{$R *.dfm}
procedure ClassA.FuncAssign(FP1: FuncPointer2;x,y:integer);
begin
if assigned(fp1) then fp1(x,y);
end;
procedure ClassA.FuncAssign(FP1: FuncPointer1;x:integer);
begin
if assigned(fp1) then fp1(x);
end;
procedure ClassA.Test(X, Y: Integer);
begin
showmessage(inttostr(x+y));
end;
procedure ClassA.Test(X: Integer);
begin
showmessage(inttostr(x));
end;
procedure ClassA.testA(x, y: integer);
var
p1:FuncPointer1;
p2:FuncPointer2;
begin
p1:=test;
FuncAssign(p1,x);
p2:=test;
FuncAssign(p2,x,y);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
with classA.Create do
testA(1,2);
end;
end.




 
L

lyco

Unregistered / Unconfirmed
GUEST, unregistred user!
我试过了,darkiss得答案在D5和D6中都可以通过。
谢谢darkiss,差不多就可以接受darkiss的答案了,westboy2000的答案(我用过的)
显然远远不如darkiss。
关于这个问题,是因为我正在写一个很复杂的算法,是关于字符串处理的。为了简化程
序,其中用到了无数的overload过程和函数指针调用(如果不这样就更复杂了)。
要不然,没有谁会平白无故想出个这么奇怪的问题的吧?
不过darkiss的答案仅仅是针对我提出的问题有效,因为我的实际问题是这样的,其中用
到了类:

type
class TestClass =
public
...
procedure Test(X: Integer)
overload
//类中的方法
procedure Test(X, Y: Integer)
overload
//类中的方法
end;

FuncPointer1 = procedure(X: Integer) of object
//指针是方法指针
FuncPointer2 = procedure(X, Y: Integer) of object
//指针是方法指针

procedure FuncAssign(FP1: FuncPointer1)
overload

procedure FuncAssign(FP1: FuncPointer2)
overload

var
ClassTest1:ClassTest;

开始我还以为普通函数指针和方法指针处理是一样的,结果我把darkiss的处理方式
移植到实际程序中时,这样写:
funcAssign(FuncPointer1(@ClassTest1.Test))

唉,结果这回的错误是:“Variable required”。

darkiss,我已经至少可以给你100分了,你能否把“加强”后的问题再解答一下?
太太太谢谢了!!!!!!!!!!

 
D

darkiss

Unregistered / Unconfirmed
GUEST, unregistred user!
test1和test2如果没有用到类成员变量的话可以声明成class function 这样才可以通过类而
不是类的实例来引用.如果你用到类成员变量,那么就要创建一个该类的对象.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }

class procedure Test(X: Integer)
overload;
class procedure Test(X, Y: Integer)
overload;
end;

FuncPointer1 = procedure(X: Integer);
FuncPointer2 = procedure(X, Y: Integer);


procedure FuncAssign(FP1: FuncPointer1)
overload;
procedure FuncAssign(FP1: FuncPointer2)
overload;

var
Form1: TForm1;

implementation

{$R *.dfm}

class procedure TForm1.Test(X: Integer);
begin
showmessage('1')
end
class procedure TForm1.Test(X, Y: Integer);
begin
showmessage('2')
end
procedure FuncAssign(FP1: FuncPointer1);
begin
showmessage('3')
Fp1(1)
end
procedure FuncAssign(FP1: FuncPointer2);
begin
showmessage('4')

end
////////////////////////////////// here /////////////////////////
procedure TForm1.Button1Click(Sender: TObject);
begin
funcAssign(FuncPointer1(@TForm1.test))
//类方法 即 class procedure

end;

end.
 
D

darkiss

Unregistered / Unconfirmed
GUEST, unregistred user!
对不起,我看得太快,误解你的问题.

对于你的后一个问题,简单的方法是这样

funcAssign(FuncPointer1(@ClassTest.test)
这个是利用delphi的一个小'bug',不保证在以后的版本中可用.这种用法也是不合语法规范的.
尽量不要这么去做.

另外,test应该是public或published.....

 

Similar threads

S
回复
0
查看
947
SUNSTONE的Delphi笔记
S
S
回复
0
查看
768
SUNSTONE的Delphi笔记
S
S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
924
SUNSTONE的Delphi笔记
S
顶部