奇怪的想法:create后,怎样在类内部把对象实例变量置为nil?

donil 2009-10-30 05:18:48

TForm1 = class(TForm)
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; Override;
end;

。。。

var
frmA: TForm1;
begin
frmA := TForm1.create(nil); //怎样在创建完成后,在类内部的代码中,把frmA置为nil
。。。
end;


不知道构造函数create没有返回值,不知道怎么把实例的地址给变量的,我想要达到这样的目的:

重载create或者什么方法,在create实例化对象完成后,把本应该赋值的变量给置为nil,如上例中,frmA := TForm1.create(nil); 后,frmA仍然是nil,这个可以做到吗?

我想可能能做,因为create返回一个实例,应该有方法可以找到这个实例的首地址是给哪个变量的,如果找到这个方法,就可以这么做了,可惜我不会,求助一下,谢了。。。
...全文
374 35 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
wxieyang 2009-11-01
  • 打赏
  • 举报
回复
如果你想实现单例模式,那么,稍稍修改下就可以了
type
TMyObj = class(TObject)
private
FID: Integer;
public
constructor Create;
end;

{ TMyObj }

constructor TMyObj.Create;
{$J+}
const
SObj: TMyObj = nil;
{$J-}
begin
if SObj = nil then
begin
SObj := Self;
FID := 1;
end
else
begin
FID := 2;
asm
mov ebx, esi
test dl, dl
jz @@exit
mov ebx, esi
mov eax, ebx
mov edx, [eax]
call dword ptr [edx - $1c]
mov dl, $01
mov ecx,[eax]
call dword ptr [ecx-$04]
pop dword ptr fs:[$00000000]
add esp, $0c
mov esi, [SObj]
mov ebx,0
@@exit:
end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
a: TMyObj;
begin
a := TMyObj.Create;
ShowMessage('单例-对象地址:' + IntToHex(Integer(a), 8));
end;

wxieyang 2009-11-01
  • 打赏
  • 举报
回复
如果你想让Create返回你需要的地址,可以在最后的那个 mov esi,0 上处理
比如你定义了个变量SObj,那么,你可以 mov esi, [SObj],则返回的就是你定义的那个SObj
wxieyang 2009-11-01
  • 打赏
  • 举报
回复
我不清楚你到底要干什么,但是如果你单纯想让Create返回空,还是可以办到的
type
TMyObj = class(TObject)
public
constructor Create;
end;

{ TMyObj }

constructor TMyObj.Create;
asm
mov ebx, esi
test dl, dl
jz @@exit
mov ebx, esi
mov eax, ebx
mov edx, [eax]
call dword ptr [edx - $1c]
pop dword ptr fs:[$00000000]
add esp, $0c
mov esi, 0
mov ebx,0
@@exit:
end;

procedure TForm1.Button1Click(Sender: TObject);
var
a: TMyObj;
begin
a := nil;
a := TMyObj.Create;
if a <> nil then
a.Free
else
ShowMessage('空');
end;


上面这段代码,每次调用都会返回一个nil,但是对象还是被创建了,也就是说,你每次创建,都将在内存中产生一个谁也找不到的对象。
这有什么意义呢?纯粹是在浪费内存
lake_cx 2009-11-01
  • 打赏
  • 举报
回复
如果可以把Create用protected隐藏起来,发布一个CreateInstace的静态procedure,参数用var的类型。强制使用者在创建对象时传入引用地址,CreateInstace中将该引用地址保存至静态成员数组中,当该对象释放时从成员数组中找到与Self指针一致的地址,并置空。
agang200008 2009-11-01
  • 打赏
  • 举报
回复
具体的也没有看明白,我对这种的理解是:
自己Create的对象,要自己释放,然后再设为nil,

比如:tempList := TStringList.Create();
tempList.Free();
tempList := nil;
donil 2009-11-01
  • 打赏
  • 举报
回复
其实现在我想实现的,就是,在c := TCCC.Create(self)后,c的值为nil,或其它我希望的地址,代码实现应该在TCCC内部实现,而不是
c := TCCC.Create(self);
c := nil;

为什么我认为这个也许是可以实现的呢?因为create并没有定义Result,说明创建的self实例也许是在其它地方赋值给c的,这样,也许我就可以修改这个值,让它指向我希望它指向的地址。

Seamour,我水平低,的确不知道NewInstance的用途,我一开始是用过NewInstance,但是,NewInstance似乎只在TObject实现,而我实际使用中,单例模式的类是从TForm继承的,用了NewInstance来实现单例,的确是可以,但是,创建的实例,完全没有TForm的特性,不能show,也不能接受sendmessage发过来的消息,就放弃了。

看了26楼的连接,我又有了点想法,但是我不了解NewInstance,前面回复的都是高手,谁愿意指导我一下,解释下NewInstance?

26楼的文中,有以下代码:


class function TSingleton.NewInstance: TObject;
begin
if ( not Assigned( Instance ) ) then
begin
Instance := inherited NewInstance;
// Initialize private variables here, like this:
// TSingleton(Result).Variable := Value;
end;
Result := Instance
Inc( Ref_Count );
end;


Result := Instance是什么意思呢?难道create返回的实例,就是NewInstance的Result?我试了下好像又不是,在我的例子里,总是报错。

我实现单例模式的方法和别人的不太一样,如果能实现,应该是比较好的方式,我还想多了解些,看看能不能实现,无论能否实现,之后都会帖出代码。

谢谢各位了。
shadowstar 2009-10-31
  • 打赏
  • 举报
回复
不能换一种思路解决这个问题吗?
function CreateObj(AOwner: TComponent): TObj;
begin
try
Result := TObj.Create(AOwner);
except
Result := nil;
end;
end;
lihuasoft 2009-10-31
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 lihuasoft 的回复:]
Delphi(Pascal) code
constructor TObj.Create;begin
Self :=nil;end;
[/Quote]

胡答...赚点可用分 -_-
lihuasoft 2009-10-31
  • 打赏
  • 举报
回复

constructor TObj.Create;
begin
Self := nil;
end;
Harryfin 2009-10-31
  • 打赏
  • 举报
回复
是要做单例而已么。就用刘艺那本书里说的方法就行了,用{$J+}在类的方法里隐藏对象实例,如果直接通过Create访问就报错。稍微扩展下就可以做成可继承的单例,请参考http://harryfin.spaces.live.com/blog/cns!31E57C5D97ECDF5!419.entry

再简单点的,用类方法加上局部全局变量就可以了。

有些东西不用太讲求完美,达到效果就行。

ps. 2010允许对继承方法的可见性降级了?不然怎么隐藏构造函数?
Seamour 2009-10-31
  • 打赏
  • 举报
回复
还是没看明白要干嘛,不过看你折腾的麻烦劲儿,看来是只知道重载 AfterConstruction 不知道重载 NewInstance
阿发伯 2009-10-31
  • 打赏
  • 举报
回复
说说我的看法,不一定正确。我也明白楼主的意思,只是觉得无论是重构构造过程,还是重载AfterConstruction方法,都不可能满足LZ要求,因为在对象内部,根据this指针(self)只能确定对象本身的地址,楼主的要求无非是想根据这个地址反过来找到代表这个对象地址的变量,并将其置为nil,这显然是不现实的,这就好比要求用一个只有next指针的单向链表的某个项去反推它的上个项一样。即使12楼说的,也只能针对全局变量,而且一个对象的地址也有可能有多个变量。
我在11楼的办法,应该还是有一定的的可行性的,就是用类的静态方法代替构造函数,这样,就可以在某种条件下返回nil,C++中经常采用这种形式,如C++版的Gdiplus中,Bitmap、Graphic类就是采用的这种办法代替构造函数。
一孔之见,仅供参考。
wxieyang 2009-10-31
  • 打赏
  • 举报
回复
delphi2010应该能完成你的想法:
将原来的Create隐藏到 private
然后在public域定义一个类方法,名字叫Create并返回一个TObject(也就是模拟构造方法)
在这个函数内部调用隐藏的构造函数Create,然后返回一个nil
gwhdaxia 2009-10-31
  • 打赏
  • 举报
回复
没搞懂道理要什么
ok1411 2009-10-31
  • 打赏
  • 举报
回复
不太明白..
Harryfin 2009-10-31
  • 打赏
  • 举报
回复
26楼的方法刘艺那本书也有说,不过有个问题就是,假如TChildSingleton继承TSingleton,如果先访问TSingleton的话,以后再从TChildSingleton来访问的话,实际还是之前的实例而已,这将会导致出问题。不考虑继承就没什么问题。
huangheguyun 2009-10-31
  • 打赏
  • 举报
回复
没有释放内存,会出错的。
dinoalex 2009-10-31
  • 打赏
  • 举报
回复
http://edn.embarcadero.com/article/22576
ahjoe 2009-10-31
  • 打赏
  • 举报
回复
报歉,没仔细阅读
ahjoe 2009-10-31
  • 打赏
  • 举报
回复
简单啊!定义一个成员,指针类型,指向你想置为 nil 的变量。
加载更多回复(15)

5,927

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧