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返回一个实例,应该有方法可以找到这个实例的首地址是给哪个变量的,如果找到这个方法,就可以这么做了,可惜我不会,求助一下,谢了

解决方案 »

  1.   

    想制造内存泄漏?  frmA := nil;
      TForm1.create(nil);  //怎样在创建完成后,在类内部的代码中,把frmA置为nil
     或
      frmA := TForm1.create(nil);  //怎样在创建完成后,在类内部的代码中,把frmA置为nil
      frmA := nil; 
      

  2.   

    不是这样的,要在类的内部实现,外部就frmA := nil就可以了。内存泄漏是不会的,其实需要把frmA置为nil时,创建的实例已经释放了,但是,frmA := TForm1.create(nil);  ,即使实例已经释放,frmA仍然不是nil,有值的,但是指向无效的内存块,我就是要在这种情况下,把frmA给置nil。
      

  3.   

    直接frmA := nil; 就行啊frmA := TForm1.create(nil);  只是让其自己负责释放资源
      

  4.   

    即使实例已经释放,frmA仍然不是nil?
    使用freeandnil(frmA)来释放。你是希望创建失败时,能返回nil,避免frmA被后续使用?
      

  5.   

    主要是写了个公用的类,在create内部释放了刚创建的实例后,就把实例指向的frmA置为nil,可以让调用者判断实例化是否成功,如果不置nil,调用者没法判断create的结果,我不希望用异常的方式提醒调用者。
      

  6.   

    我是希望,把实例指针置nil的代码,放在类内部实现,而不是在类外部,由调用create的用户来做=nil的操作。这个功能对我现在的代码应该还算有用吧,就是不知道怎么实现,没头绪。
      

  7.   

    frmA := TForm1.create(nil);
    TForm.Create方法的参数指的是返回对象的拥有者,传递nil只不过是表示该对象没有拥有者而已。
      

  8.   


    忘了构造函数是否能返回nil的
    不过你可以这样:
    type
      Pform=^Tform1;
    procedure newobj(f:Pform);
    begin
      f^ := TForm1.create(nil); 
      if 失败 then
       f^:=nil;
    end;
      

  9.   

    FreeAndNil不是吗?? 还是我理解错了?
      

  10.   

    1、这样算不算procedure TForm1.Button1Click(Sender: TObject);
    begin
      Self := nil;
      if Self = nil then
        ShowMessage('nil nil');
    end;
    2、要确保释放的实例变量都是nil,把XXX.Free方法改成FreeAndNil(XXX)
      

  11.   

    不知你说的是否下面这个样:type
      TMyObj = class
      public
        class function CreateObj(IsFree: Boolean): TMyObj;
      end;{ TMyObj }class function TMyObj.CreateObj(IsFree: Boolean): TMyObj;
    begin
      Result := TMyObj.Create;
      if IsFree then
        FreeAndNil(Result);
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      Obj: TMyObj;
    begin
      Obj :=  TMyObj.CreateObj(True);
      if Obj = nil then
        ShowMessage('nil');
    end;
      

  12.   

    没办法,不过可以搜索映像的全局数据段,匹配指针的值,然后将该指针置空。
    简单做法,取Application全局对象的地址,按字节往下搜,将搜到的地址看成PPointer,将其内容与Self指向的地址比较,如果相等则将搜到的地址中的内容置空。
    试验过,可行,不过没这个必要,而且如果有那么巧合可能会搜索错误。
      

  13.   

    可能是我表达有问题,导致估计只有lake_cx理解了我的意思,呵呵,等下我还是把我的代码贴上来吧,主要是前不久看到有人说单例模式在delphi2010之前不能很好的实现,所以就尝试着写了个,思路差不多,也就是用个类方法创建个局部实例返回,然后在create中用异常来阻止正常使用create方法创建实例,但我不喜欢异常,就重载了AfterConstruction方法去释放实例,这样,用户可以用类方法去创建单个实例,用create方法,也不会报异常,但是这就带来一个问题,调用create创建实例后,虽然没有异常、也没有创建新的实例,但对象变量却不是nil,会导致使用者不能判断实例是否已经被创建,所以,就有了这个想法,在AfterConstruction把实例释放后,把对象变量置为nil,让调用者可以判断,甚至,可以把已经存在的单个实例的地址给那个对象变量,完美实现单例模式。
      

  14.   

    单例模式?工厂模式?
    重载构造函数,在函数末尾加入
    asm
      xor eax,eax
    end;
    试试,通常Windows下都是用eax返回值的。给他清零,或者搞清楚nil的二进制表示,直接mov进去。
      

  15.   

    哦,对了,nil的二进制表示就是0
      

  16.   


    constructor TObj.Create;
    begin
      Self := nil;
    end;
      

  17.   

    不能换一种思路解决这个问题吗?
    function CreateObj(AOwner: TComponent): TObj;
    begin
      try
        Result := TObj.Create(AOwner);
      except
        Result := nil;
      end;
    end;
      

  18.   

    简单啊!定义一个成员,指针类型,指向你想置为 nil 的变量。
      

  19.   

    delphi2010应该能完成你的想法:
    将原来的Create隐藏到 private 
    然后在public域定义一个类方法,名字叫Create并返回一个TObject(也就是模拟构造方法)
    在这个函数内部调用隐藏的构造函数Create,然后返回一个nil
      

  20.   

      说说我的看法,不一定正确。我也明白楼主的意思,只是觉得无论是重构构造过程,还是重载AfterConstruction方法,都不可能满足LZ要求,因为在对象内部,根据this指针(self)只能确定对象本身的地址,楼主的要求无非是想根据这个地址反过来找到代表这个对象地址的变量,并将其置为nil,这显然是不现实的,这就好比要求用一个只有next指针的单向链表的某个项去反推它的上个项一样。即使12楼说的,也只能针对全局变量,而且一个对象的地址也有可能有多个变量。
      我在11楼的办法,应该还是有一定的的可行性的,就是用类的静态方法代替构造函数,这样,就可以在某种条件下返回nil,C++中经常采用这种形式,如C++版的Gdiplus中,Bitmap、Graphic类就是采用的这种办法代替构造函数。
      一孔之见,仅供参考。
      

  21.   

    还是没看明白要干嘛,不过看你折腾的麻烦劲儿,看来是只知道重载 AfterConstruction 不知道重载 NewInstance
      

  22.   

    是要做单例而已么。就用刘艺那本书里说的方法就行了,用{$J+}在类的方法里隐藏对象实例,如果直接通过Create访问就报错。稍微扩展下就可以做成可继承的单例,请参考http://harryfin.spaces.live.com/blog/cns!31E57C5D97ECDF5!419.entry再简单点的,用类方法加上局部全局变量就可以了。有些东西不用太讲求完美,达到效果就行。ps. 2010允许对继承方法的可见性降级了?不然怎么隐藏构造函数?
      

  23.   

    http://edn.embarcadero.com/article/22576
      

  24.   

    26楼的方法刘艺那本书也有说,不过有个问题就是,假如TChildSingleton继承TSingleton,如果先访问TSingleton的话,以后再从TChildSingleton来访问的话,实际还是之前的实例而已,这将会导致出问题。不考虑继承就没什么问题。
      

  25.   

    其实现在我想实现的,就是,在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?我试了下好像又不是,在我的例子里,总是报错。我实现单例模式的方法和别人的不太一样,如果能实现,应该是比较好的方式,我还想多了解些,看看能不能实现,无论能否实现,之后都会帖出代码。谢谢各位了。
      

  26.   

    我不清楚你到底要干什么,但是如果你单纯想让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,但是对象还是被创建了,也就是说,你每次创建,都将在内存中产生一个谁也找不到的对象。
    这有什么意义呢?纯粹是在浪费内存
      

  27.   

    如果你想让Create返回你需要的地址,可以在最后的那个 mov esi,0 上处理
    比如你定义了个变量SObj,那么,你可以 mov esi, [SObj],则返回的就是你定义的那个SObj
      

  28.   

    如果你想实现单例模式,那么,稍稍修改下就可以了
    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;
      

  29.   

    具体的也没有看明白,我对这种的理解是:
    自己Create的对象,要自己释放,然后再设为nil,比如:tempList := TStringList.Create();
    tempList.Free();
    tempList := nil;
      

  30.   

    如果可以把Create用protected隐藏起来,发布一个CreateInstace的静态procedure,参数用var的类型。强制使用者在创建对象时传入引用地址,CreateInstace中将该引用地址保存至静态成员数组中,当该对象释放时从成员数组中找到与Self指针一致的地址,并置空。