一般继承 /虚方法 跳过父类执行 祖父类的方法
Posted 是蓝蓝的呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一般继承 /虚方法 跳过父类执行 祖父类的方法相关的知识,希望对你有一定的参考价值。
背景:某一天不小心把基类函数写成了 虚函数virtual,子类override 重写时,有同事需要跳过父类执行祖父类的方法代码;
发现 T祖父类(self).**方法(),时异常。因为虚函数转型为祖父类时,是多态的形式,还是会执行本子类的方法,所有造成一种循环执行代码,造成栈溢出 ;
网上百度到 hack的函数 找到祖父类的方法基地址 执行。
解决一:不用虚方法,一般的继承即可。
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TMyClassA=class(TStringList) public procedure KKK();// virtual; end; TMyClassB=class(TMyClassA) public procedure KKK();//override; end; TMyClassC=class(TMyClassB) public procedure KKK(); //override; end; TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private { Private declarations } A:TMyClassA; B:TMyClassB; C:TMyClassC; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TMyClassA.KKK(); begin ShowMessage(\'TMyClassA.KKK\'); end; procedure TMyClassB.KKK(); begin inherited; ShowMessage(\'TMyClassB.KKK\'); end; procedure TMyClassC.KKK(); begin //inherited; 注释后 不就不执行 TMyClassB.KKK() // TMyClassA(self).KKK; ShowMessage(\'TMyClassC.KKK\'); end; procedure TForm1.FormCreate(Sender: TObject); begin A:=TMyClassA.Create ; B:=TMyClassB.Create; C:=TMyClassC.Create; end; procedure TForm1.Button1Click(Sender: TObject); begin A.KKK; end; procedure TForm1.Button2Click(Sender: TObject); begin B.KKK; end; procedure TForm1.Button3Click(Sender: TObject); begin C.KKK; end; end.
解决二:虚拟方法跳过父类继承调用祖父类的代码 http://blog.csdn.net/coolbaby/article/details/485652
此方法已经本人亲自验证过,可行。
procedure TCurrentObject.AVirtualMethod; begin asm MOV EDX,VMTOFFSET AVirtualMethod // 虚拟方法VMT偏移量 MOV EAX,Self // 对象实例 => EAX MOV ECX,[EAX] // 类VMT => ECX MOV ECX,[ECX].vmtParent MOV ECX,[ECX] // 父类VMT => ECX MOV ECX,[ECX].vmtParent MOV ECX,[ECX] // 祖父类VMT => ECX MOV ECX,[ECX+EDX] // 祖父类虚拟方法地址 => ECX CALL ECX // 方法调用 end; end;
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TMyClassA=class(TStringList) public procedure KKK(); virtual; end; TMyClassB=class(TMyClassA) public procedure KKK();override; end; TMyClassC=class(TMyClassB) public procedure KKK(); override; end; TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private { Private declarations } A:TMyClassA; B:TMyClassB; C:TMyClassC; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TMyClassA.KKK(); begin ShowMessage(\'TMyClassA.KKK\'); end; procedure TMyClassB.KKK(); begin inherited; ShowMessage(\'TMyClassB.KKK\'); end; procedure TMyClassC.KKK(); begin //inherited; 注释后 不就不执行 TMyClassB.KKK() // TMyClassA(self).KKK; //虚方法时会异常,循环调用, asm MOV EDX,VMTOFFSET KKK // 虚拟方法VMT偏移量 MOV EAX,Self // 对象实例 => EAX MOV ECX,[EAX] // 类VMT => ECX MOV ECX,[ECX].vmtParent MOV ECX,[ECX] // 父类VMT => ECX MOV ECX,[ECX].vmtParent MOV ECX,[ECX] // 祖父类VMT => ECX MOV ECX,[ECX+EDX] // 祖父类虚拟方法地址 => ECX CALL ECX // 方法调用 end; ShowMessage(\'TMyClassC.KKK\'); end; procedure TForm1.FormCreate(Sender: TObject); begin A:=TMyClassA.Create ; B:=TMyClassB.Create; C:=TMyClassC.Create; end; procedure TForm1.Button1Click(Sender: TObject); begin A.KKK; end; procedure TForm1.Button2Click(Sender: TObject); begin B.KKK; end; procedure TForm1.Button3Click(Sender: TObject); begin C.KKK; end; end.
以上是关于一般继承 /虚方法 跳过父类执行 祖父类的方法的主要内容,如果未能解决你的问题,请参考以下文章
如果父类有一个虚方法,子类重写了这个方法。那么子类到底有没有继承父类的虚方法??
C++中,子类会继承父类的虚函数表!对于父类的析构函数(虚函数) 也会继承吗?