老概以前说过:构造顺序和一般对象的构造是一样的,只不过它构造函数的地址不是编译时确定,而是运行时确定。构造函数可以virtual对于VCL这种类库的设计至关重要,它允许创建程序编译时未知的类实例,只要该类的基类已知就可以。VCL中凡是支持设计时的组件都必须继承自TComponent或者它的派生类,而TComponent的构造函数就是virtual的。
https://bbs.csdn.net/topics/392069877————————
当时不太理解,后来知道Delphi有一个类类型,TClass。
不过这句不太理解:
它允许创建程序编译时未知的类实例
VCL中什么类型是编译时未知的呢?如果窗体上放一个按钮,类型不就是TButton吗?

解决方案 »

  1.   

    比如在IDE中安装了第三方组件,IDE可以在设计时实例化某些组件,这些组件的类就是在IDE自身编译时未知的
      

  2.   


    第三方组件放上去的时候,IDE也知道它的类型亚,比如TImageEn。
      

  3.   

    IDE自身编译的时候并不知道TImageEn是什么,甚至那时TImageEn还不存在,TImageEn的相关信息是IDE在运行时通过RTTI获得的
    简单说,非virtual构造函数的地址是编译时确定的,因此无法创建在程序自身编译时还不存在/未知的类的实例,典型如存在于另一个二进制模块(比如包)中的类
      

  4.   


    把一个ImageEn控件放在窗体上,然后编译项目,编译器不知道ImageEn控件的类型吗?
      

  5.   


    把一个ImageEn控件放在窗体上,然后编译项目,编译器不知道ImageEn控件的类型吗?

    实际上IDE面对的只是TComponent或者TControl这两种类型的派生类。
    那么拖拽一个控件到设计器上,设计器创建这个实例的时候都是当做TComponent创建的,他可不知道是不是TImageEN。但是因为构造函数是虚的,而且有比CPP更加厉害的RTTI信息,一个类知道自己是什么,是谁派生出来的,于是能正确的创建自己。可以理解为所有能在设计期间可见的组件都是TComponentClass的一种,也就是class of TComponent.
    对于IDE来说不关你是什么,我都按照TComponentClass调用构造函数就行了
      

  6.   


    把一个ImageEn控件放在窗体上,然后编译项目,编译器不知道ImageEn控件的类型吗?

    实际上IDE面对的只是TComponent或者TControl这两种类型的派生类。
    那么拖拽一个控件到设计器上,设计器创建这个实例的时候都是当做TComponent创建的,他可不知道是不是TImageEN。但是因为构造函数是虚的,而且有比CPP更加厉害的RTTI信息,一个类知道自己是什么,是谁派生出来的,于是能正确的创建自己。可以理解为所有能在设计期间可见的组件都是TComponentClass的一种,也就是class of TComponent.
    对于IDE来说不关你是什么,我都按照TComponentClass调用构造函数就行了不是特别理解,为什么:
    拖拽一个控件到设计器上,设计器创建这个实例的时候都是当做TComponent创建的,他可不知道是不是TImageEN
      

  7.   

    IDE通过RTTI,是可以从设计时包里面获取组件的类型的,还有属性类型和事件原型,但是创建对象实例的时候,不需要针对每一种类型单独创建(也不可能),能够以统一的方式建立,比如:
    function CreateObject(AClass: TClass): TObject;
    begin
      Result := AClass.Create;
    end;
    之后就可以:
    var
      a, b, c: TObject;
    begin
      a := CreateObject(TComponent);
      b := CreateObject(TPanel);
      c := CreateObject(TBitmap);
      writeln('a is a ', a.ClassName);
      writeln('b is a ', b.ClassName);
      writeln('c is a ', c.ClassName);
    end;
      

  8.   


    但是创建对象实例的时候,不需要针对每一种类型单独创建(也不可能),能够以统一的方式建立
    ————
    是不是这样理解,如果针对每一种类型单独创建,就需要:
    class TButton;
    class TPanel;
    class TListBox;
    等等把所有类全部前置声明一遍?
      

  9.   

    Delphi的RTTI&VMT
      

  10.   


    问题在于,IDE本身被编译的时候,并不知道有没有某些类,比如N多的第三方组件,当时这些类甚至还没有被写出来,所以它不可能以xxx.Create;或者new xxx;这种方式创建设计时组件实例。
      

  11.   


    问题在于,IDE本身被编译的时候,并不知道有没有某些类,比如N多的第三方组件,当时这些类甚至还没有被写出来,所以它不可能以xxx.Create;或者new xxx;这种方式创建设计时组件实例。
    明白了