type
TMyClass = class(TObject)
constructor Create;
end;var
c: TClass;
begin
c := TMyClass; // 如何通过变量c,获取TMyClass的构造函数地址呢?
// c.Create只会TObject的构造函数,不会调用到TMyClass的构造函数end;
解决方案 »
- 城里人,你知道真正的猪肉应该是什么样,什么味道吗??
- 怎样写代码?为DBGridEH的第一列加上checkbox复选框,这一列存储的是每条记录的id值,用户可以多选,对多条记录进行批量删除
- tClientDataSet如何排序?似乎没有类似TAdoDataSet.sort的属性
- 高手们··如何在select语句中加入一个排序列???急!!!!!!!!!
- delphi有没有一个函数可以返回以某个分割符分开的字符串的各部分?
- ^-^女友今天過生日^-^差點忘記了~~~^-^~~開始散分^-^生日快樂^-^ 200分(2)
- 简单问题:怎样将Access,SQL Server数据库的表导入Excel中,及Access和SQL Server互导!
- 查询后的报表
- LoadItemListToCombox
- 关于串口通讯控件——SPCOMM如何检测到串口有设备?
- 再有一个SCPOMM的问题,为什么我的接收缓存器Buffer的数据,不会自动清除呢?
- delphi 问题
Tfoo = class
public
constructor bar1;
constructor bar2; overload;
constructor bar2(foofoo: Integer); overload;
end;1. Tfoo 有好几个 constructor,应该得到哪个?
2. bar1 和 bar2 都不是虚方法,凭什么出现在 vmt 中?
你的 MyClass 在调用 TMyClass.Create 的时候根本不需要查 vmt
2、你说的对,我忽略这个问题了。不过其实我的意思是,是否有办法可以调的到呢?如果对AClass进行手工转型,如TMyClass(AClass).Create,是可以调用到的,但是不转型就不行。现在我想设计通用的程序,所以不可能进行手工转型。因此想看看有没什么方法可以解决这个问题。PS. 我一直都在怪TOBJECT的构造函数为什么不声明成虚函数,嫌virtual占空间多的话用dynamic也行嘛。
多说一句,你的 TMyClass 并不是一个好的命名方式,按照 delphi 的命名习惯,容易让人认为 TMyClass = class of TMy,或者只是一个不需要实例化的函数包
多说一句,c 系列语言的构造函数都没法是虚函数,cpp 还有看起来“更过分”的限制连在构造函数里调用虚函数都不行,这些你都想过为什么吗?delphi 能提供虚函数的构造函数就已经很不寻常了,不是只有想不到没有做不到
--------------------------------------------------
我一开始问的时候也是问地址
从 oo 的角度说,你不要指望给不是自己设计的东西非常容易的加上“通用性”。至于 TClass,恐怕除了枚举类名之类的情况外,我的代码中是从来不会出现的。
----------------------------------------------------
TClass太常用了,FindClass一个例子
多说一句,c 系列语言的构造函数都没法是虚函数
----------------------------------------------------
这个有所理解。不过其实你也要明白,DELPHI的构造函数也很特殊,它其实只是一个普通的函数。从类引用上调用构造函数,和从对象引用上调用构造函数,是不一样的,足以看出这点。
你要是懂汇编的话,我也不用解释了,自己就该明白都是怎么回事了直接地址的意思是,比如TA = class
constructor CreateA;
end;TAClass = class of TA;TB = class
constructor CreateB; virtual;
end;TBClass = class of TB; TAClass(TA).CreateA; {1}
TBClass(TB).CreateB; {2}1生成的代码是
call $004abcdefg
这是个地址在编译期就决定好了的,也就是个常数。对于每个不同的class来说,这个常数都是不一样的。你有100个 class 就得写100个 case 才能“通用”,而且每引入一个 class 还得手动往里加2生成的代码是
mov eax, [TB]
call [eax + VMT_Offset_of_CreateB]
也就是说,要根据该 TBClass 指向的 vmt 中某一偏移量的地址决定调用什么代码
除非要使用 vcl 的固化机制,不然我不用 FindClass/GetClass 这种既没效率还得写代码的东西
constructor 也没啥特殊的,只是有个隐含参数而已。delphi 传隐含参数的地方太多了,这要是特殊的话,那 function foo: string 也特殊,dynamic 方法也特殊,procedure foo(x: array of T) 也特殊……平时写的东西里就没几个不特殊的了。
VCL系统中典型的模式是TComponent及其派生类.
关键在于TComponent的构造函数是虚函数.
所以楼主想要用这种设计模式不应该从Tobject派生.而是应该创建属于自己的一个基础类.有它自己的虚构造函数.这样从它派生的子类就可以享受这样的待遇了.type
TMyBase = class(TObject)
constructor Create; virtual;
end; TMyBaseClass = class of TMyBase; //这里应该用类类型 TMyClass = class(TMyBase)
constructor Create; override;
end;{ TMyClass }constructor TMyClass.Create;
begin
Inherited Create;
OutputDebugString('TMyClass.Create;');
end;{ TMyBase }constructor TMyBase.Create;
beginend;var
c: TMyBaseClass;//这里应该用类类型
cc : TMyBase;
begin
c := TMyClass;
cc := c.Create;
end;
我完全明白你说的方法。不过我的框架需要解决动态调用构造函数的问题。
在D2010里面用反射就可以了,在之前的版本还没有办法
Container.RegisterService(TypeInfo(IService), TypeInfo(TService));
Container.InjectConstructor(TypeInfo(TService), @TService.Create, ['123456', 789]);P.S. 不过咋一看这种方法好像不支持overloaded的constructor
话说回来,虚函数/继承也只不过就是个函数指针而已,根本没有你所说的没有多态、继承的问题。oop 只是在语法上作出规定,然后由编译器维护 rtti 之类的东西而已。
还有一种办法,可以写个 memory manager,只写 GetMem 的部分就够了,除了调用原来的 GetMem 外,再判断一下是否是由 TObject.NewInstance 调用的,如果是的话,ebx 就是类指针
当然,就不能c: TClass了,而应该c: class of TBase;
procedure bar; overload;
procedure bar(V: Integer); overload;
end;如何获得这两个 Tfoo.bar 的地址么?
type
TBar0 = procedure of object;
TBar1 = procedure(V: Integer) of object;
var
method1, method2: TMethod;
foo: Pointer;
begin
foo := Tfoo;
TBar0(method1) := Tfoo(@foo).bar;
TBar1(method2) := Tfoo(@foo).bar;
{ method1.Code = procedure Tfoo.bar }
{ method2.Code = procedure Tfoo.bar(V: Integer) }
end;procedure foobar2;
var
foo: Pointer;
bar0: procedure of object;
bar1: procedure(V: Integer) of object;
begin
foo := Tfoo;
bar0 := Tfoo(@foo).bar;
bar1 := Tfoo(@foo).bar;
{ @bar0 = procedure Tfoo.bar }
{ @bar1 = procedure Tfoo.bar(V: Integer) }
end;需要说明的是,中间变量 foo 是为虚方法或动态方法服务的,普通成员函数直接用 nil 就够了。