Delphi接口编程的两大陷阱

2016-01-29 14:26 11 1 收藏

Delphi接口编程的两大陷阱,Delphi接口编程的两大陷阱

【 tulaoshi.com - Delphi 】

  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。

OBJ2 := TC2.Create;

try

Intf1 := OBJ2;

Intf1.D

来源:http://www.tulaoshi.com/n/20160129/1493305.html

延伸阅读
标签: 孕前
“基因tulaoShi.com改造”可打造完美宝宝? 近日,美国科学家利用试管受精技术,实现对卵子DNA中的遗传缺陷进行改造,成功培育出4只健康的基因改造猴宝宝。这种新型技术将很快可以被用 于改造有缺陷的人类卵子,避免生下有严重遗传疾病的婴儿。但是,由于这种基因改造宝宝从生理学上来说将拥有两母一父,因此引发...
标签: 丰胸
坚挺来自5分钟精油按摩 胸部精油按摩运动成效:每个动作重复8-10次,每天5分钟,紧实胸部肌肉,加强支撑力,让您的胸部越来越挺。 倒少量调好的按摩油在手上(或者直接滴在胸部上),然后均匀的涂抹在胸部。在按摩过程中如果感到按摩起来不是很滋润,即有涩的感觉时随时再加少量按摩油。 按摩手法可以分四步来进行: 1、以大拇指一边,另外...
标签: 化妆
①眉毛过于杂乱时,可以轻刷透明睫毛膏加以改善。如果眉毛过于稀疏,画眉后,用眉刷蘸少量同色系的睫毛膏,由眉头刷至眉梢,提升浓密感。 ②用眉粉晕染眉色时,准备同色系的深、浅色眉粉,浅色可以使用在眉头前半部分,补足眉色。深色用来于描画眉峰与眉梢,最后用眉梳轻刷使深浅色自然过渡,立体眉形自然呈现。 延伸阅读: ...
标签: 护肤 美容 保养
一、以冷水洗脸 每天早上在洗完脸后,将冰块放进洗脸盆,然后把脸浸入冰水中约5秒钟,脸离开冰水后立刻用手拍打脸颊,这个动作约重复10-30次。 二、洗脸时做按摩 肌肤适当的刺激,帮助肌肤深层血液及淋巴液循环,加速新陈代谢。你可以利用每天洗脸或是涂抹化妆水、乳液的时候,轻轻地做脸部按摩,洗脸乳液的泡沫及乳...
标签: 健康常识
两大秘诀告别白领压力 当长期性的压力,譬如不停地工作或为财务问题而持续困扰,却会对我们的身体造成损害,出现心悸和胸部疼痛、头痛;胃部不适、腹泻、恶心或呕吐、免疫力降低;情绪波动、失眠、过度吸烟喝酒、注意力难集中等。如何在保证工作效果的前提下排解压力,找回健康的自己? 让身体减压 专家指出,不要用吃东...

经验教程

191

收藏

46
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部