procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);
var
  Instance: TComponent;
begin
  Instance := TComponent(InstanceClass.NewInstance);
  TComponent(Reference) := Instance;
  try
    Instance.Create(Self);
  except
    TComponent(Reference) := nil;
    raise;
  end;
  if (FMainForm = nil) and (Instance is TForm) then
  begin
    TForm(Instance).HandleNeeded;
    FMainForm := TForm(Instance);
  end;
end;以上代码是TApplication用来产生Form的源代码,如果使用以下一段代码似乎更为简洁:
procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);
var
  Instance: TComponent;
begin
  try
    TComponent(Reference) := InstanceClass.Create(nil);
  except
    TComponent(Reference) := nil;
    raise;
  end;
  if (FMainForm = nil) and (TComponent(Reference) is TForm) then
  begin
    TForm(Reference).HandleNeeded;
    FMainForm := TForm(Reference);
  end;
end;请问下面这一段代码和上面的有啥区别?

解决方案 »

  1.   

    这可能与系统编译时的优化有关,不太明白,反正有时候,DELPHI就是非得来倒一下才行,比如赋值时也有此类问题,直接代进去就不行,先赋一个就可以,不懂,关注!
      

  2.   

    3.实例变量与类变量可以通过两种方法在类中存储数据───作为实例变量和类变量.实例变量是特定于对象的,如果你有两个对
    象(即一个类的两个实例),每一个对象中的实例变量独立于另一个对象中的实例变量的;另一方面,两个对象的
    类变量均指向相同的数据,并因此面保存相同的值,换句话说,类变量被类中的所有对象共享.差点忘了,它们在
    形式上的区别,类变量在声明时比实例变量多一个static.
    eg:
    class data
    {
    public int intdata=0;//显然,intdata在这儿是实例变量
    }
    public class exam
    {
    public static void main(String[] args)
    {
    data a,b;
    a=new data();
    b=new data();
    a.intdata=1;
    System.out.println("b.indata="+b.intdata);
    }
    }
    运行结果:
    b.intdata=0
    结果分析:
    可以看出,a.intdata的值虽然变了,但并没有影响b.intdata.但是如果在data类中声明intdata时,在其前
    面加上static就变成类变量了(即:public static int intdata=0;),则此时运行结果会变为:
    b.intdata=1
    这次a.intdata值的改变可把b.intdata影响了,事实上,对象a和b的类变量均指向相同的数据,所有值一
    样,这就是类变量的作用.不知道我的理解对不对
    var
      Instance: TComponent;
    这个应该是个类变量
      

  3.   

    在实际应用中最好不要用TApplication.CreateForm()来建立对象
      

  4.   

    感谢楼上的诸位的答复和支持。其实这个疑问不是凭空而生的,而是在阅读李维的《VCL架构剖析》一书的过程中产生的。第二章在谈到TObject的创建时谈到:
    aBobj := TBase.Create;
    其实和以下的程序代码效果相同:
    var
      aBobj: TBase;
      aObj: TObject;
    begin
      ...
      try
        aObj := TObject(TBase.NewInstance);
        aBobj := TBase(aObj.Create);
      finally
        FreeAndNil(aBobj);
      end;
    ...
    end;然后列举了TApplication中的CreateForm的例子,说这个代码采用的就是第二种方法。但文中没有提及为什么采用第二种,而不采用第一种方式的原因。我已经给李维发了一个邮件咨询这个问题,但不知能不能有回复。
      

  5.   

    class function TObject.NewInstance: TObject;
    begin
      Result := InitInstance(_GetMem(InstanceSize));
    end;
    procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);
    var
      Instance: TComponent;
    begin
      Instance := TComponent(InstanceClass.NewInstance);//这里分配了内存空间,看上面的函数
      TComponent(Reference) := Instance;//把Instance的地址给了Reference;
      try
        Instance.Create(Self);//在这里创建对象,实例化...
      except
        TComponent(Reference) := nil;//创建失败的话,将Reference的地址设置成nil;
        raise;//抛出异常
      end;
      if (FMainForm = nil) and (Instance is TForm) then//下面是关于主窗口的,与今天话题无关
      begin
        TForm(Instance).HandleNeeded;
        FMainForm := TForm(Instance);
      end;
    end;
      

  6.   

    有点不一样:
    请注意两段代码:
     try
    Instance.Create(Self);
    except

    --------------------
    楼主的是:
     try
    TComponent(Reference) := InstanceClass.Create(nil);
    except

    -----------------------
    楼主的代码中,创建实的申请内存过程在try 范围内
    而原来的代码中,newInstance分配对象内存在try之外。
    我想,这就是你要找原因了,
    记得哪本书里说过,在try 里面做分配内存的操作相当危险。至于为什么,我再查查
      

  7.   

    TComponent的Create很奇怪的,可能有部分代码是不可见的...
      

  8.   

    也许更多的奥秘都隐藏在create里面了吧,我现在感觉是李维的一个误导,上面的那两个代码效果可能不同。谢谢大家。结贴