昌邑做网站的公司,承德市建设局网站,成都网站建设g冠辰,谷歌推广课程11.1.3 混合引用中的错误
在使用对象时#xff0c;你通常应该只使用对象变量或接口变量来访问它们。混合使用这两种方法会破坏对象 Pascal 所提供的引用计数机制#xff0c;并可能导致极难跟踪的内存错误。在实践中#xff0c;如果你决定使用接口#xff0c;你可能应该…11.1.3 混合引用中的错误
在使用对象时你通常应该只使用对象变量或接口变量来访问它们。混合使用这两种方法会破坏对象 Pascal 所提供的引用计数机制并可能导致极难跟踪的内存错误。在实践中如果你决定使用接口你可能应该只使用基于接口的变量。
下面是许多可能的类似情况中的一个例子。假设你有一个接口、一个实现接口的类和一个将接口作为参数的全局过程
typeIMyInterface interface[{F7BEADFD-ED10-4048-BB0C-5B232CF3F272}]procedure Show;end;TMyIntfObject class(TInterfacedObject, IMyInterface)
publicprocedure Show;
end;procedure ShowThat(AnIntf: IMyInterface);
beginAnIntf.Show;
end; 这段代码看起来相当琐碎而且百分之百正确但可能出错的地方是你调用过程的方式该代码是 IntfError 示例的一部分
procedure TForm1.BtnMixClick(Sender: TObject);
varAnObj: TMyIntfObject;
beginAnObj : TMyIntfObject.Create;tryShowThat(AnObj);finallyAnObj.Free;end;
end; 在这段代码中发生的情况是我将一个普通对象传递给了一个期待接口的函数。鉴于对象确实支持接口编译器在调用时没有问题。问题出在内存管理方式上。
起初对象的引用计数为零因为没有接口指向它。进入 ShowThat 过程后引用计数增加到 1。现在在退出存储过程时引用计数减少并归零因此对象被销毁。换句话说当你将 AnObj 传递给过程时它就会被销毁这确实有点尴尬。如果运行这段代码就会出现内存错误。
这种问题可以有多种解决方案。你可以人为地增加引用计数并使用其他低级技巧。但真正的解决办法是不要将接口和对象引用混用而只使用接口来引用对象此代码再次取自 IntfError 示例
procedure TForm1.BtnIntfOnlyClick(Sender: TObject);
varAnIntf: IMyInterface;
beginAnIntf : TMyIntfObject.Create;ShowThat(AnIntf);
end; 在这种特定情况下解决方案非常简单但在许多其他情况下却很难编写出正确的代码。同样经验法则是避免混合使用不同类型的引用。不过请继续阅读下一节了解一些最新的替代方法。