对象的方法一样得符合这个法则,我们编写一个类:如
TA=Class
proceudre Func(...);//方法原形;
end
Procedure TA.Func(...) //方法实现的地方,静态编译后,调入内存运行时,会产生一个入口地址.
begin
....
end;
TA.func就标识着这个地址 你可以通过@TA.func取得这个方法的地址,这和一般的方法一样,都只是内存当中的一个地址而已,编译器并没有因为它是一个对象的方法而特别的对待,即然如此,我们当然也可以当这个方法如一般方法一样的调用,你在程序当中写下如此:
begin
asm
call TA.func.
end
end
如此调用完全可以成立,甚至完全可以运行,只是有一些风险(这个跟你函数代码内容有关).
的确大多数资料都这样写着:对象的方法只能通过对象调用,想当初,我也是这么毕恭毕敬的遵守着这样的条列,完全没有去想想背后到底是个什么原理,还有的资料写着:当基类继承父类后,它就继承了父类的数据成员和方法,我一时也没想明白:方法可以继承?方法是怎么继承的?我一时也弄不清这话是从哪个角度来考量的.
一个很好的方法就是查看Cpu的汇编码,通过汇编码幕后的东西暴露无遗.
var obj:TA
obj.func(...),这就是标准的对象方法调用,我们查看汇编,一般会看到如下形式:
mov EAX,[OBJ];将obj对象的地址,送入了EAX..
Call TA.Func;//调用那个静态编译后的方法,这和调用一般方法没啥两样...
唯一不同的是,对象地址被送入了EAX寄存器,这是干什么?delphi默认的函数调用惯例是寄存器调用惯例,用寄存器来传递参数!也就是说将obj对象当作一个参数一样传递了,这就是对象方法调用的惯例:对象当作参数传,然后就调用那个TA.FUNC,就这么简单.
我们平常说的对象方法内部那个self指针就是这个参数,传对象是有理由的:毕竟是对象方法,内部要能访问对象的数据成员或其它什么东西,但对象的数据成员在另一个块内存上,你不传递这个内存的地址,怎么能定位到它的数据成员?如果传递一个对象的地址(对象就代表着那块内存的地址),万事ok..
但有一些小小的有趣的东西总是存在:你看着第一步,将对象做为参数传递,参数么?我想传啥就啥,确实你
mov eax,0,电脑也拿你也没办法.问题是我不传一个对象,该方法可以执行吧?有时候行,有时候不行,当你的对象方法,没有用到对象任何的数据成员或其它东西,肯定能执行.这时你肯定会想到类方法,就是这么回事,类方法当中就是不能访问对象的成员.为你省事,delphi帮你做好调用.
另外一个就是我传一个别的对象,可以吧?当然可以!这个方法属于一个对象,但我却传递了另外一个对象的地址,方法可以执行吧.可以,只要那个对象有着和这个对象相同的数据成员,肯定可以正确执行.这时,你应该可以想到什么情况下一个对象有另一个对象的相同的据成员,继承!子类肯定拥用父类相同的数据成员,这也解释了为什么子类可以执行父类的方法,但反过来不一定行得通.
关于对象的方法我能讲的就是这么多,我不是大师,只是说说自己的理解,随手记之,说不定对人有用,以后也可以自己看看.