升级了,散分!还有一个关于IUnknown的问题。

snowfog 2003-10-20 11:03:55
问题:在Delphi中如何实现用IUnknown编写的类库?我想用它的多重继承功能。

在Delphi中,接口是主要为了COM而编写的,但也可以用于普通应用程序的类库中,这就遇到了问题,没有一个为普通应用程序设计的IUnknown的实现类,我仿照COM的接口编写了一个,但实现起来有问题,在将IUnknown接口在多个对象之间传递时发现问题多多,主要是由于应用计数的问题。各位看有什么好的解决方案?
...全文
65 点赞 收藏 30
写回复
30 条回复
snowfog 2003年10月28日
FrameSniper(§绕瀑游龙§) :
那我怎样才能将一个实体保存起来,而且还要用一种标准类型,例如TObject?
回复 点赞
tears0 2003年10月28日
接分and顶!
回复 点赞
sailer_shi 2003年10月22日
帮你顶一下
回复 点赞
wangjiki1111 2003年10月22日
偷分喽!!!
回复 点赞
FrameSniper 2003年10月22日
个人认为这里和引用计数没有任何关系!
回复 点赞
FrameSniper 2003年10月22日
unit Unit1;

interface

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

type
ISomeIntf=interface
['{BF6DDEA6-8DFB-4BFB-9A99-D3969E91B98D}']
procedure IntfProc;
end;
TSomeCoClass=class(TInterfacedObject,ISomeIntf)
procedure IntfProc;
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
vSomeIntf:ISomeIntf;
vSomeCoClass:TSomeCoClass;
vInParam,vOutParam:TObject; //模拟入、出参
begin
vSomeCoClass:=TSomeCoClass.Create ; //创建实现类对象
vSomeIntf:=vSomeCoClass as ISomeIntf; //获取接口指针,这里引用计数将加1
vInParam:=TObject(vSomeIntf); //转换,转换结果无意义,即vInParam是一个
//无意义的对象指针
vOutParam:=vInParam as TSomeCoClass; //这个转换依然无意义
ShowMessage(vOutParam.ClassName ) //这里将要访问无意义对象指针对应的VMT,而
//此VMT是根本不存在的,所以出现AV错误
//引用计数减1
end;

{ TSomeCoClass }

procedure TSomeCoClass.IntfProc;
begin
ShowMessage('Test');
end;

end.

注:不知道楼主是否是出的这种错误?你传递入参的时候其实就已经发生错误,接口只是栈上对应的一个指针,接口在堆上是没有实体的,因为它是协议,所以你转换后得到的TObject类型的对象指针实际是没有意义的,按常规这个指针应该有对应的堆上的对象实体与它对应,但实际是没有的,所以你试图通过这个指针去访问对象是肯定要报AV错误的!
回复 点赞
FrameSniper 2003年10月22日
昨天下午试验了个东西,可惜CSDN太破了,要今天才能贴上来,郁闷....
回复 点赞
wzds2000 2003年10月22日
顶。。。
回复 点赞
halfdream 2003年10月22日
比如,在SCONNECT单元中,可以找到类似处理的代码
在procedure TTransportThread.Execute;函数中,
将IDataBlock接口POSTMESSAGE以前,把它的引用计数加1..
接收方把引用计数减1..


回复 点赞
halfdream 2003年10月22日
>var
> FTestParent: ITestParent;

>我是这样存的
> TObject(FTestParent)
>我是这样取得
> FTestParent as TTestParent
> ~~~~~~~~~~~\ITestParent你这儿是你的笔误吗?


你把参数类型定为IUnknown要好得多吧?
你是不是把接口引用的对象保存在TLIST之类的地方,用TOBJECT方式保存?

将ITestParent作为TObject型变量传递时候,引用计数并没有增加,
你保存的时候,原来的接口变量释放,这个对象引用减为0,对象释放,
再想取它出来,当然会出错.

解决办法之一,是在保存的时候,引入计数加一.


回复 点赞
halfdream 2003年10月21日
我也曾为引用计数烦过,不过回想起来,它带来的甜头应该更多..
回复 点赞
Linux2001 2003年10月21日
我同意 pankun(剑神一笑 ^_^) 的方法
回复 点赞
xiangwangz 2003年10月21日
up
回复 点赞
snowfog 2003年10月21日
halfdream(哈欠) :
我是一段时间以前用这个出的问题,所以现在都改成了抽象基类来代替接口,但它实现不了多重继承,我认为多重继承在设计类库时还是很有用处的。
我正在试原来使用接口出的问题。
回复 点赞
FrameSniper 2003年10月21日
不知道楼主为什么要这么传递?

首先,楼主需要明白一点,接口与它的实现类之间是赋值兼容的!也就是说可以将实现类对象直接赋予接口变量。接口变量也是栈上的一个指针,所以楼主的TObject(FTestParent)的转换是允许的,这样转换后等于让编译器对原有指针内存空间的解释发生改变。当你获取的时候,由于FTestParent已经为TObject类型,所以实际是进行向上引用,和具体接口已经没有什么关系了....不明白你这里会出什么样的错误!?
回复 点赞
blueshrimp 2003年10月21日
不会
回复 点赞
snowfog 2003年10月21日
接口类型的变量可以按照TObject传递吗?我试了传递时可以,再取出来时就取不正确了。
var
FTestParent: ITestParent;

我是这样存的
TObject(FTestParent)
我是这样取得
FTestParent as TTestParent
回复 点赞
随风飘摇的小小草 2003年10月21日
up
回复 点赞
nyf1220 2003年10月21日
接口的引用记数可以自己释放掉,
一般借口和类混合使用会引起内存错误
所以,一般使用借口变量。
回复 点赞
Seahilly 2003年10月20日
up
回复 点赞
发动态
发帖子
语言基础/算法/系统设计
创建于2007-08-02

3420

社区成员

3.3w+

社区内容

Delphi 语言基础/算法/系统设计
社区公告
暂无公告