1。书中52页提到,Application.CreateForm的代码如下:
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;
...
end;
这个问题和本书关系不大,只是在书上看到想起来了,这段代码我觉得用如下的写法效果也是一样的:
begin
  try
    TComonent(Reference):=InstanceClass.Create();
  except
    Reference:=nil;
    raise;
  end;
end;
原始代码先用NewInstance方法申请内存,再用Create方法进行初始化,并且如果Create过程中产生异常,则置Reference为空。
我觉得我写的代码也可以达到这样的效果,所以想问一下它们到底有什么区别,我想Delphi中原始的写法总是由它的道理的

解决方案 »

  1.   

    2。这个也是看书时想到的,
    书上65页左右提到“一旦使用重载方法之后,那么编译器便会以对象变量声明的类型作为邦定的依据,而不是执行期以对象变量的实际内容为准”,对此我写了一段简单的测试程序:
      TBase = class (TObject)
      protected
        function Fun():String;overload;virtual;
      end;  TDerived = class(TBase)
      protected
        function Fun():String;overload;
      end;function TBase.Fun():String;
    begin
      Form1.Memo1.Lines.Add('TBase.Fun()');
      Result:='hello';
    end;function TDerived.Fun():String;
    begin
      Form1.Memo1.Lines.Add('TDerived.Fun()');
      Result:='hello';
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      o:TBase;
    begin
      o:=TDerived.Create();
      try
        o.Fun();
      finally
        o.Free;
      end;
    end;此时调用Button1Click后,确实调用了TBase.Fun()函数,但是如果将以上类声明中的overload关键字都去掉,再与性程序,答案还是这样,
      TBase = class (TObject)
      protected
        function Fun():String;virtual;
      end;  TDerived = class(TBase)
      protected
        function Fun():String;
      end;
    我认为:没有调用TDerived中的Fun函数,只是因为它没有override中的同名函数,而和overload关键字无关,不知道各位大虾是怎么认为的??
      

  2.   

    1,实在看不出来,一定要说有点区别的话,那就是当NewInstance失败时,你的版本会将Reference设为nil,而原来的不会改动Reference的值2,在你的第2个声明中,Derived有两个Fun(),一个继承于Base,一个是静态函数,
    o变量声明为Base类型,
    o.Fun调用的自然是虚函数,也就是Derived从Base中继承的Fun(),又由于Derived并没有override Base的Func(),所以最终实际调用的还是Base.Func(),这是很自然的
    这和重不重名实际上没有关系,和overload也没有关系
      

  3.   

    第一个问题还是不解。。希望高人回答。第二个问题,照 alphax(多喝了三五杯) 你的说法,同意我的观点,在这里函数是否声明成overload是没有关系的咯?那样的话,李维说的“一旦使用重载方法之后,那么编译器便会以对象变量声明的类型作为邦定的依据,而不是执行期以对象变量的实际内容为准”就是错的了
      

  4.   

    还是老兄学习比较认真,其实CreateForm我以前也看过几回了,从没有发现这个不同写法的问题,,
    按老兄的说法,还有一种写法更简洁procedure TApplication.CreateForm(InstanceClass:TComponentClass;var Reference);
    var
      Instance:TComponent;
    begin
      Instance := InstanceClass.Create(Self);
      TComponent(Reference) := Instance;  ...
    end;
      

  5.   

    怎么又是同样的问题,如果照你的写法当然不行,关键在于Instance.Create(self);这句请参考http://expert.csdn.net/Expert/topic/2684/2684694.xml?temp=.3415949
      

  6.   

    这个写法不行,为什么?能不能详细说说,,你说的>>Instance.Create(Self);这句>>这里的Instance已经一个实例,而不是一个类了,Create已经一个override的一个由
    >>Instance调用的普通方法了,它已经不再是构造函数
    我的观察是这样的,构造函数比普通类对象函数多一个隐含的参数,这个隐含参数是DL参数
    我叫它construction_flag, 它实际上是一个枚举类型,

    CF_INITED_AND_WANT_SEH = -1 (< 0)
    时,表示实例已经初始化,但是需要一个SEH框架来确保构造期间发生异常时能够释放实例
    对应于Instance.Create的情形CF_INITED_AND_DONT_WANT_SEH = 0
    表示实例已初始化且无需SEH,通常是忽略对_ClassCreate的调用,这种情况我没看过CF_UNINITED_AND_WANT_SEH = 1 (> 0)
    表示实例尚未初始化且需SEH,对应于InstanceClass.Create的情形这个参数由编译器根据上下文来(到底是类调用的,还是对象调用的)插入一句代码来初始化
    如mov dl, 1或者mov dl, -1所以我觉得,Instance.Create(Self)调用的仍然是构造函数,只不过参数不同而已。因为构造函数除了初始化实例以外,还执行构造SEH的工作,
    也就是说Instance.Create不单纯是调用Create里面的代码,它还嵌入了一个SEH
    Instance.Create
    实际上等于
    try
      Instance.AnyProcessInCreate;
      ...
    except
      Instance.Free;
      raise; 
    end;
    这一点可以从_ClassCreate函数中看出来不过以前有个贴子曾经讨论过_ClassCreate,好像是一个叫烧鸡翅开的贴,提到一个
    Instance2 := Instance1.Create(...);
    不能正常工作的问题,因为Instance1.Create不会分配实例,所以不能正确工作所以在这一点上Instance.Create和InstanceClass.Create有所不同
    而且
    Instance := InstanceClass(InstanceClass.NewInstance);
    Instance.Create(...);
    的形式比较高级,因为我们可以在Create以前执行一些特殊的操作比如Delphi的IDE也许是这样干的:Comp := TAnyCompClass(TAnyCompClass.NewInstance);
    Comp.ComponentState := Comp.ComponentState + [csDesigning];
    Comp.Create(FormOrDataModule);但是,不管怎么说,我还是没看出,这里的Instance := InstanceClass(InstanceClass.NewInstance);
    Instance.Create(...);和Instance := InstanceClass.Create(...);有什么不同