一个让我不解的问题(关于对象的)(20分)

  • 主题发起人 主题发起人 iforward
  • 开始时间 开始时间
I

iforward

Unregistered / Unconfirmed
GUEST, unregistred user!
这些天正在看<<delphi面象对象编程>>
对象在内存中的首4个字节应该是存方指向虚拟表的指针,但我更改了其指向
虚方法表的指针后,却没效果,有人知道这是为什么吗?
谢谢,(本人还有一百多点分了,就少给点了)
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TMan = class ;
TChinese = class;
PTData = ^TData;
TData = record
Name:string;//名字
Age:Integer;//年龄
Sex:Boolean;//true为男人,false为女人
end;
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
Edit4: TEdit;
Edit5: TEdit;
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
FPerson:TMan;
FP:Pointer;
FPInt:PInteger;
FPData:PTData;
FPstr:PChar;
public
{ Public declarations }
end;



TMan = class
private
Name:string;//名字
Age:Integer;//年龄
Sex:Boolean;//true为男人,false为女人
public
constructor Create();
function ShowName():string;virtual;
function ShowAge():integer;virtual;

end;

TChinese = class(TMan)
private
Language:string;
public
constructor Create();
function ShowName():string;override;
function ShowAge():integer;override;
end;

var
Form1: TForm1;

implementation

constructor TMan.Create;
begin
Name:='No Name';
Age :=100;
sex :=true;
end;



function TMan.ShowAge: integer;
begin
result:=self.Age;
end;

function TMan.ShowName: string;
begin
result:=self.Name;
end;

{ TChinese }

constructor TChinese.Create;
begin
Name:='fangchunfei';
Age:=15;
sex:=true;
end;



function TChinese.ShowAge: integer;
begin
result:=self.Age;
end;

function TChinese.ShowName: string;
begin
result:=self.Name;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
P,PTemp:Pointer;
N,M:integer;
FTemPerson:TMan;
begin
Memo1.Lines.Clear;
FPerson:=TChinese.Create;

Memo1.Lines.Add('Name:'+FPerSon.ShowName);
Memo1.Lines.Add('Age:'+ IntToStr(FPerSon.ShowAge));

FP:=@FPerson;

P:=FP;
P:=Pointer(P^);
N:=Integer(P);
Memo1.Lines.Add('此时FPerson为指向TChinese对象');
Memo1.Lines.Add('FPerson对象首地址: '+IntToHex(N,8)) ;
N:=Integer(P^);
Memo1.Lines.Add('FPerson中虚表的地址:'+ IntToHex(N,8));

//强行改变FPerson对象中指向的虚表指针,让其指向父类对象中的虚表
FTemPerson:=TMan.Create;
PTemp:=Pointer(FTemPerson);
M:=Integer((PInteger(PTemp))^);
N:=Integer(PTemp);
N:=N+4;
Memo1.Lines.Add('FTemPerson对象中虚表的地址: '+IntToHex(M,8)) ;

FP:=Pointer(FPerson);
P:=FP;
N:=Integer(P);
N:=N+4;
FPData:=PTData(N);
Memo1.Lines.Add('FPData 测试,FPData.Name : '+FPData^.Name);
Memo1.Lines.Add('FTemPerson对象中虚表的地址: '+IntToHex(M,8)) ;
Memo1.Lines.Add('改变前FPerson中指向虚表的地址:'+ IntToHex(Integer(P^),8));
Integer(P^):=M;
Memo1.Lines.Add('改变后FPerson中指向虚表的地址:'+ IntToHex(Integer(P^),8));


Edit3.Text:=FPerson.ShowName();//却是没有调用父类中ShowName,为什么啊?
N:=N+4;
PInteger(N)^:=200;
Edit4.Text:=IntTostr(PInteger(N)^);
Edit5.Text:=IntTostr(FPerson.showage);
FPerson.Free;

FTemPerson.Free;
end;

end.
 
老大,面向对象的实现原理是这样的,但这不是用来改着玩的啊——这样很有意思吗?!
如果要深入了解编译器的实现,只要设定断点看看Delphi生成的汇编代码即可——这些深
层次东西源码体现不出来的。
 
我就是不太明白啊,书上写的是指向虚表的,所以我来验证一下
楼上的有必要说一堆没有实质性的套话吗
 
楼主的代码很复杂,我以为下面的代码就足以说明问题:

type
TC1=class
protected
FA:Integer;
public
property A:Integer read FA;
procedure DoA
virtual;
end;
TC2=class(TC1)
public
procedure DoA
override;
end;

{ TC1 }
procedure TC1.DoA;
begin
FA:=FA+10;
end;

{ TC2 }
procedure TC2.DoA;
begin
FA:=FA+8;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
o1,o2:TC1;
begin
o1:=TC1.Create;
o2:=TC2.Create;
o1.DoA;
o2.DoA;
Memo1.Lines.Add(Format('o1.A=%d o2.A=%d',[o1.A,o2.A]));
PInteger(o2)^:=PInteger(o1)^
//改变VMT,使其指向父类的VMT
o2.DoA
//调用父类的DoA方法
Memo1.Lines.Add(Format('o1.A=%d o2.A=%d',[o1.A,o2.A]));
end;
 
多谢楼上的,其实我的程序注释的那个&quot;为什么没有调用父类的方法&quot;地方
已经调用了父类的方法,只是父类和子类中都是用到了self.Name结果,导至没看出效果来
楼上的程序简洁明了,能够很好的说明问题
至于我的程序为什么那么长,是因为我还要验证对象的成员问题,以及多态中的一些问题
总之还是感谢楼上的.
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
654
import
I
I
回复
0
查看
763
import
I
后退
顶部