欢迎来到天天文库
浏览记录
ID:46866407
大小:39.00 KB
页数:15页
时间:2019-11-28
《Delphi接口和编程两大陷阱》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库。
1、.....Delphi接口和编程两大陷阱Delphi接口和编程两大陷阱2012-06-0100:20150人阅读评论(1)收藏举报Delphi接口编程的两大陷阱前一阵写了一个通过接口扩展功能的例子,当时由于指针和接口的转换,导致了很多错误,最近又接触到了一个类和接口混用的例子,导致程序的指针在传递中变了地址或者内容,导致读到了错误的地址,现在将接口和类之间的情况进行一下汇总。陷阱一、接口的类型转换陷阱 (1)不能把一个对象引用强制转换成这个引用的类型没有声明实现的接口,即使这个对象实际实现了这个接口(呵呵,优点拗口)。 (2)学习参考.....当把一个对
2、象变量赋给一个接口变量,在把这个接口变量赋还给对象变量时,这个对象变量的地址已经变了,也就是不再是原来的对象了,而是指向一个错误的地址。例如:I1=interfacefunctionDo:Boolean;end;TC1=classATT1:Integer;end;TC2=Class(TC1,I1)ATT2:Integer;functionDo:Boolean;end;Intf1:I1;学习参考.....OBJ1:TC!;OBJ2:TC2;OBJ2:=TC2.Create;OBJ1:=OBJ2.I1(OBJ2).DO;正确。I1(OBJ1).DO;编译失败因为
3、OBJ1的类型TC1没有声明实现I1所以不能转换成I1,即使OBJ1确实实现了I1。如果把对象转为接口再转回来也会有问题。OBJ2:=TC2.Create;OBJ2.ATT1:=0;Intf1:=OBJ2;//正确。OBJ2:=Intf1;学习参考.....TC2(Intf1).ATT1:=0;//运行期非法地址访问错误。OBJ2.ATT1:=0;//运行期非法地址访问错误。也就是,从对象引用转换成指针引用后,地址改变了,但是由指针引用再转回对象引用时地址没有变回来(Delphi的bug?)。陷阱二、接口的生存期管理我认为接口是不需要生存期管理的,因为接口根
4、本不可能生成真正的对象。但是Delphi却又一次打击了我的常识(咦,为什么要说“又”呢?),它的接口是有生存期的,而且必须实现以下三个方法:functionQueryInterface(constIID:TGUID;outObj):HResult;stdcall;function_AddRef:Integer;stdcall;function_Release:Integer;stdcall;学习参考.....每次都要实现这三个方法是比较麻烦的,而且更重要的是,我不知道Delphi什么时候用以及怎么用这三个方法?所以我也不知道怎么实现这三个方法。如果不想自己实
5、现这三个方法,你可以使用TComponent。因为TComponent已经实现了这三个方法,所以可以从它继承,就不用实现这三个方法了。这样就可以放心使用了吗?答案是否定的。因为Delphi在你把接口变量置为nil时偷偷的(因为很出乎我的意料)调用了_Release。function_IntfClear(varDest:IInterface):Pointer;varP:Pointer;beginResult:=@Dest;ifDest<>nilthen学习参考.....beginP:=Pointer(Dest);Pointer(Dest):=nil
6、;IInterface(P)._Release;end;end;而_Release时又做了什么呢?functionTComponent._Release:Integer;beginifFVCLComObject=nilthenResult:=-1//-1indicatesnoreferencecountingistakingplace学习参考.....elseResult:=IVCLComObject(FVCLComObject)._Release;end;不是Com对象的话,就什么也没作。我们作的不是Com对象,是不是就没有任何问题了呢?答案依然是否定的,
7、考虑如下情况:OBJ2:=TC2.Create;tryIntf1:=OBJ2;Intf1.DO;FinallyOBJ2.Free;Intf1:=nil;学习参考.....End;会怎么样呢?会出非法地址访问错误。为什么?上面说过把接口引用设为nil时,会调用_IntfClear,而_IntfClear又会调用对象的_Release,而这时这个对象已经释放了,自然就出非法地址访问错误啦。有人说多此一举吗,接口引用只是个地址,没必要手动设为nil。OBJ2:=TC2.Create;tryIntf1:=OBJ2;Intf1.DO;FinallyOBJ2.Free;
8、End;学习参考.....结果可能还会出你的意料,还
此文档下载收益归作者所有