一个在csdn讨论很激烈的问题,可还是没有解决,来此寻找答案(20分)

  • 主题发起人 主题发起人 devecom
  • 开始时间 开始时间
D

devecom

Unregistered / Unconfirmed
GUEST, unregistred user!
具体参考: http://www.csdn.net/expert/topic/328/328923.shtm

unit Unit1;

interface

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

type
IX = interface
['{41AB2EA3-E950-4285-BF3C-2F07ECF5DDF4}']
procedure xx;
end;
IY = interface
['{70FBB89C-6528-4A40-A624-432F61D98B03}']
procedure yy;
end;
TXY = class
a: IX;
b: IY;
public
procedure xy;
end;

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

var
Form1: TForm1;

implementation

{$R *.dfm}

{ TXY }

procedure TXY.xy;
begin
a.xx
//没错
showmessage('a');
b.yy
//错了, 为什么?
end;

procedure TForm1.Button1Click(Sender: TObject);
var c: TXY;
begin
c.xy
//按下之后的事件在上面的程序有问题。
end;

end.

想不通为什么在b.yy会出错,而a.xx不出错
 
像这么玩儿,不出错是你命大,呵呵。
调用 a.xx 和b.yy 时,程序会跳到对象的虚拟方法表去寻找
虚拟方法指针,可是在你的代码里,虚拟方法表根本没有初始化,
a.xx 能无错运行是因为它的虚拟方法表的地址正好与另一个函数
的开头地址重合(为什么有这么巧的事情,我也说不上来)
而b.xx运行报错是因为没那么好运。

要想说明问题,简单的改一下TXY的定义就可以了,在

TXY = class
i:integer;
a: IX;
b: IY;
public
procedure xy;
end;

这时候a.xx铁定报错

这是因为,有了i 就影响了 a 在内存中的位置,也影响了a 中本该指向虚拟方法表
那个指针的位置,所期望得到的虚拟方法表地址自然和上回的也不一样,于是落得
和b.YY一个下场。


 
补充一下,把 i 放到 a 后面估计不会有事
 
var c: TXY;
begin
c.xy
//按下之后的事件在上面的程序有问题。
end;

[blue]问题一:对象不创建就用了?[/blue]

TXY = class
a: IX;
b: IY;
public
procedure xy;
end;

[blue]问题二:接口似乎不是怎么用的[/blue]
中央试试:TXY = class(TObject, IX, IY)
 
当我写成TXY=class(TObject,Ix,Iy)的时候delphi说QueryInterface,_AddRef,等未定义,
这是IunKnown实现的吧?怎么会呢?我把ComObj等单元都加进去了,我知道这没必要,看
Delphi帮助说那些是在system单元定义的,但system是系统默认就有的,这是为什么呢?

还与,我感觉问题并不是报了一个错那么简单,而是整个程序都有问题,就象yysun所说,
接口不是这样用的。

哪位能给了详细的例子吗?
 
知道了QueryInterface的定义,应该是
TXY=class(TInterfacedObject,Ix,Iy)
TObject并没有QueryInterface的实现
 
具体方法必须被申明.[:)]
unit Unit1;

interface

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

type
IXP = interface
['{831E118D-4730-44FC-88BB-A652B4E98730}']
procedure XX;
end;

IYP = interface
['{F0984084-7BB6-40D8-937B-6520A5E957E2}']
procedure YY;
end;

TXYP = class(TinterfacedObject, IXP, IYP)
public
procedure XY;
procedure XX;
procedure YY;
end;

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

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TXYP.XY;
begin
XX;
ShowMessage('A');
YY;
ShowMessage('B');
end;

procedure TXYP.XX;
begin
//
end;

procedure TXYP.YY;
begin
//
end;

procedure TForm1.Button1Click(Sender: TObject);
var
A : TXYP;
begin
A.XY;
end;

end.
 
lanny的方法可以,但不知道是否还有更好的方法
 

接口定义的函数都是纯虚拟的,一定要由你来实现,所以只有像yysun和landy那样做。

补充一下,我前面的回帖只是解释了为什么你危险的调用a.xx却能大难不死,但绝不是
说那样是正确的做法。
 
yySUN:
>[blue]问题一:对象不创建就用了?[/blue]
这里对象如果“创建”的话 就[red]错[/red]了,为什么?
其他问题:
问题2:为什么最开始的程序中, a.xx[red]没[/red]错?
procedure TXY.xy;
begin
a.xx
//没错
showmessage('a');
b.yy
//错了, 为什么?
end;
 
不知道你要什么更好的办法,接口是个纯虚拟的东西,没有类的实现根本就不能运行,
而且以你的写法
TXY = class
a: IX;
b: IY;
public
procedure xy;
end;
这样你根本就没有实现基本的几个接口,如QueryInterface等等
 
sorry, 我没有说清楚,我说的是在 Delphi 6 中的是用方法。
D6 中 Interface 和 D5 是有很大区别的。
http://www.delphibbs.com/delphibbs/dispq.asp?lid=596317
 
经过这翻讨论清楚多了
 
多人接受答案了。
 
后退
顶部