(1)根据Charlie Calvert的结论:me 根本不懂OOP:((0分)

  • 主题发起人 主题发起人 千中元
  • 开始时间 开始时间

千中元

Unregistered / Unconfirmed
GUEST, unregistred user!
因为‘寸光’的原因,一直没有认真解决OOP入门的问题(当然还有自己笨的原因)。以后如果没机会来大富翁请教,只有自己修行。现在请各位师傅领进门
程序:《D4技术内幕》P55
Type
Tparant=class(Tobject)
procedure Draw
virtual;
end;
Tchild=class(Tparant)
procedure draw
override;
end;
在第一种情况中,Draw 方法声明为虚拟的,在第二种情况中,它没有声明为虚拟的。当没有声明Draw方法为虚拟时,如将对象传递给CallDraw方法,将调用TPrarent的Draw 方法。

如果Draw方法声明为虚拟的,如将对象传递给callDraw,那么将调用Tchild的Draw方法, 即使是通过Tparant的实例调用。
=======不能理解上面的话!
我自己是这样“错误”理解程序的:
!---对象是parent:调用parent.draw
对象-->callDraw()--->对象传给draw!
!---对象是child:调用child.draw.

是不是老外说话偶不懂???
附源程序如下
 
忘了给分了。不多,20,接受答案就给。
附源程序如下
type
TParent = class(TObject)
procedure Draw
virtual;
end;

TChild = class(TParent)
procedure Draw
override

procedure ShowHierarchy
virtual;
end;

procedure TParent.Draw;
begin
ShowMessage('Parent Draw');
end;

procedure TChild.Draw;
begin
ShowMessage('Child Draw');
end;
procedure CallDraw(O: TParent);
begin
O.Draw;
end;

procedure FreeObject(O: TObject);
begin
O.Free;
end;

procedure TForm1.bPolymorphClick(Sender: TObject);
var
Child: TChild;
Parent: TParent;
begin
Child := TChild.Create;
Parent := TParent.Create;
CallDraw(Parent);
CallDraw(Child);
FreeObject(Child);
FreeObject(Parent);
end;
 
第一段话没看明白,
代码倒是看清楚了:
1, 如果 有virtual , override;
输出为:Parent Draw ChildDraw;
2, 有 virtual 无 override;
输出为: Parent Draw ChildDraw;
3,有 virtual 无 override, 也无 child 的 draw 声明:
输出为: Parent Draw ChildDraw;
4, 无 virtual 有 override;
编译错误。
5, 无 virtual, 无 override
(child 的 draw 覆盖 parent 的 draw)
输出为: Parent Draw ChildDraw;


未经测试,也许有不对的地方。
 
当是虚拟时:
对象是parent:调用parent.draw
但parent=child.create时就是child.draw
对象是child:调用child.draw.
 
to supperMMX,
唉,我也看不懂老外说什么?都看了N遍了,怕你们笑话,没敢问,今天受不了这折磨了!
to autumn,
对本例子,这样理解对么?
!---对象是parent:调用parent.draw
对象-->callDraw()--->对象传给draw!
!---对象是child:调用child.draw.
 
也不一定是老外说的不对,有可能翻译的不好。

前一句不太对吧。
就象 autumn 所举的例子,未测试,不敢妄说。
 
autumn,(不会把你问怕了吧。。呵呵)
我怎么在书上type 下没有找到 Procedure CallDraw(o:Tparant);
如果你没有这本书,我可以把它全部贴出来。《D4内幕》P54
 
网慢!

procedure calldraw(o:tparent)
//原代码倒数第二行
 
唉,我深表同情,教育网还可以。
我是说声明。。---是该说声明么?
就是比如
type
Tform-class(tform)
bittn1:tbittn;
edit1;tedit;
procedure....
这种地方怎么没有
Procedure CallDraw(o:Tparant);?
 
这是个全局的过程,有必要声明为类的一部分吗?
 
连form的一部分也不是?
 
这个过程可以给别的地方访问,如果是form的一部分,别处要访问这个方法时
就要create,free.这就有违oop了。
这也是一个技巧。

你也太小气了,0分
 
你没看是操作失误,知道autumn兄也穷,一定会给的!
这样的?哦。。以后记着用(好象和pascal 不同)
 
声明为Virtual的成员
编译用的是滞后联编,调用时才决定用哪个成员

没有声明为Virtual的成员
用的是前期联编,编译时就决定了调用哪个成员
所以就调用了父类的成员
 
autumn,supermmx到我问的“不要应届毕业生”下留个名字:}
 

面向对象编译器在编译程序的时候,类的方法编译完毕,会给出一个地址,
如address1。

每一个类如果存在虚方法,则编译系统会生成一个此类的虚方法表(VMT),
VMT类似一个方法指针数组,其中按类中虚方法出现的顺序,记载着虚方法的地
址,如Paddress1,Paddress2等等。

每一个对象(类的实例)在编译完成后,如果类存在虚方法(对Delphi来讲,
所有的类都存在虚方法),则对象实际的内存存储状况是有两部分组成的,一部分,
是对象的字段(属性)数值,另一部分是一个指针(Pvmt),指向初始化此对象
^^^^^^^^^^^^^^^
(实例)的类的虚方法表VMT。
^^^^^^^^^^

一、如果程序中调用的是一个类的实方法,调用方法的语句直接编译成:
Call 类.address1,这个地址同对象实际上是由哪个类初始化是没有关系的。

二、如果程序中调用的是一个虚方法,则调用方法的语句就不是编译成
Call 类.address1了,而是编译成Call 对象地址.Pvmt.Paddress1)了。

因此呢,虚方法的调用实际上是对初始化这个对象(类实例)的类的方法
调用,也就是说,虚方法是根据具体的对象来调用的。

而实方法呢,则同这个对象的初始化类没有关系,也就是说,实方法的调
用不需要考虑具体的对象是什么,只是同用户暂时指定的类有关系。

说了半天,感觉象是再说绕口令 :)
 
结束先,以后再问
 

Similar threads

回复
0
查看
863
不得闲
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
后退
顶部