文章分类 | 推荐文章 | 最新文章 | 热点文章 | 最新软件 | 精品软件 | 下载排行 | 推荐下载 | 免费看大片 | WPS | 杀毒软件
清风网络
首 页 软件下载 网络学院 数码学院
QQ 电脑入门 游戏 操作系统 图形处理 办公软件 媒体动画 精文荟萃 工具软件 网络编程 程序开发 网络技术 认证考试 网站建设 文章专栏
当前位置:清风网络学院程序开发DelphiDelphi接口编程的两大陷阱
精品推荐
特别推荐
·利用Delphi编写Socket通信程序
·拦截其它程序的网络数据封包
·Delphi编程根据IP地址得到主机名
·Delphi 程序员代码编写标准指南
·用DELPHI开发自动化服务器
·将日期转化为汉语的形式
·加密ACCESS数据库增加安全性
·使用TCP/IP协议实现聊天程序
·在Delphi中控制扫描仪
热点TOP10
·Delphi中DLL的创建和使用(1)
·用Delphi实现WinSocket高级应用
·利用Delphi编写Socket通信程序
·DBGrid使用全书(三)
·DELPHI多层分布式开发(2)
·实现关键字查找word文档里相匹配的内容
·实现高速文件拷贝
·用Delphi实现动态获取版本信息
·使用TCP/IP协议实现聊天程序
·在Delphi中控制扫描仪
·实现webbrowser中的打印、复制、全选等编辑功能
·拦截其它程序的网络数据封包
·Delphi下的ADO使用方法!
·DELPHI多层分布式开发(1)
·Delphi中利用钩子实现QQ聊天窗口的修改
·Delphi多层开发方案比较
·Delphi下“培养”自己的简单木马
·Delphi数据库控件使用入门
·Delphi的拨号连接类
·在Delphi中实现数据分析模块的动态报表

Delphi接口编程的两大陷阱

日期:2007年5月2日 作者: 查看:[大字体 中字体 小字体]


陷阱一、接口的类型转换陷阱

  a) 不能把一个对象引用强制转换成这个引用的类型没有声明实现的接口,即使这个对象实际实现了这个接口(呵呵,优点拗口)。

  b) 当把一个对象变量赋给一个接口变量,在把这个接口变量赋还给对象变量时,这个对象变量的地址已经变了,也就是不再是原来的对象了,而是指向一个错误的地址。

  例如:

I1 = interface
function Do: Boolean;
end;


TC1 = Class
ATT1: Integer;
end;


TC2 = Class(TC1, I1)
ATT2: Integer;
function Do: Boolean;
end;

Intf1: I1;

OBJ1: TC!;

OBJ2: TC2;

OBJ2 := TC2.Create;
OBJ1 := OBJ2.
I1(OBJ2).DO;正确。
I1(OBJ1).DO;编译失败
  因为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?)。

  陷阱二、接口的生存期管理

  依据我的常识(此处是编程常识,不是Delphi使用常识)来讲,我认为接口是不需要生存期管理的,因为接口根本不可能生成真正的对象。但是Delphi却又一次打击了我的常识(咦,为什么要说“又”呢?),它的接口是有生存期的,而且必须实现以下三个方法:

function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
  每次都要实现这三个方法是比较麻烦的,而且更重要的是,我不知道Delphi什么时候用以及怎么用这三个方法?所以我也不知道怎么实现这三个方法。

  如果不想自己实现这三个方法,你可以使用TComponent。因为TComponent已经实现了这三个方法,所以可以从它继承,就不用实现这三个方法了。

  这样就可以放心使用了吗?答案是否定的。因为Delphi在你把接口变量置为nil时偷偷的(因为很出乎我的意料)调用了_Release。

function _IntfClear(var Dest: IInterface): Pointer;
var
P: Pointer;
begin
Result := @Dest;
if Dest <> nil then
begin
P := Pointer(Dest);
Pointer(Dest) := nil;
IInterface(P)._Release;
end;
end;
  而_Release时又做了什么呢?

function TComponent._Release: Integer;
begin
if FVCLComObject = nil then
Result := -1 // -1 indicates no reference counting is taking place
else
Result := IVCLComObject(FVCLComObject)._Release;
end;
  不是Com对象的话,就什么也没作。我们作的不是Com对象,是不是就没有任何问题了呢?答案依然是否定的,考虑如下情况:

OBJ2 := TC2.Create;
try
Intf1 := OBJ2;
Intf1.DO;
Finally
OBJ2.Free;
Intf1 := nil;
End;
  会怎么样呢?会出非法地址访问错误。为什么?上面说过把接口引用设为nil时,会调用_IntfClear,而_IntfClear又会调用对象的_Release,而这时这个对象已经释放了,自然就出非法地址访问错误啦。

  有人说多此一举吗,接口引用只是个地址,没必要手动设为nil。


[1] [2] [3] 下一页 




上一篇:没落的奇迹 谁会买下Delphi?

下一篇:用Delphi设计多边形窗体

Delphi接口编程的两大陷阱 相关文章:
·激情聊天原来有陷阱!快来揭露视频MM的真面目
·socket编程原理
·Windows黑客编程基础
·TCP/IP编程实现远程文件传输
·asp.net程序中最常用的三十三种编程代码
·Visual C++ ADO数据库编程入门
·在 C++ Builder中利用串行通信控件编程
·3D编程指南第一部分:快速进入移动JAVA 3D编程世界
·Windows下C语言网络编程快速入门
·全面图解路由器接口及连接(图)(2)
Delphi接口编程的两大陷阱 相关软件:
·死灵术士之黑暗陷阱
·C++编程思想
·战后的两大审判-《东京大审判》《纽伦堡大审判》
·DelphiV7.0
·shell编程和unix命令
·VC++编程100例
·vb编程与应用视频(1-5)
·Cgi编程傻瓜书
·ASP Web 编程实例教程(PDG)
·Delphi 4.0应用开发指南

特别声明:本站除部分特别声明禁止转载的专稿外的其他文章可以自由转载,但请务必注明出处和原始作者。文章版权归文章原始作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。如果本站转载的文章有版权问题请联系编辑人员,我们尽快予以更正。
[打印本页] [关闭窗口] 转载请注明来源:http://www.viphot.com
| 帮助(?) | 版权声明 | 友情连接 | 关于我们 | 信息发布
Copyright 2007 www.viphot.com All Rights Reserved. 鄂ICP备05000083号Powered by:viphot