Delphi:构造不调用重写的虚拟构造函数

Delphi:构造不调用重写的虚拟构造函数,第1张

概述我有一个TBitmap的示例后代: TMyBitmap = class(TBitmap)public constructor Create; override;end;constructor TMyBitmap.Create;begin inherited; Beep;end; 在运行时,我构建其中一个TMyBitmap对象,将图像加载到其中,并将其放置在窗体上的T 我有一个TBitmap的示例后代:

TMyBitmap = class(TBitmap)public    constructor Create; overrIDe;end;constructor TMyBitmap.Create;begin   inherited;   Beep;end;

在运行时,我构建其中一个TMyBitmap对象,将图像加载到其中,并将其放置在窗体上的timage中:

procedure TForm1.button1Click(Sender: TObject);var   g1: TGraphic;begin   g1 := TMyBitmap.Create;   g1.LoadFromfile('C:\...\example.bmp');   Image1.Picture.Graphic := g1;end;

在TPicture.SetGraphic中你可以看到它通过构造一个新图形并在新构造的克隆上调用.Assign来制作图形的副本:

procedure TPicture.SetGraphic(Value: TGraphic);var   NewGraphic: TGraphic;begin   ...   NewGraphic := TGraphicclass(Value.Classtype).Create;   NewGraphic.Assign(Value);   ...end;

构造新图形类的行:

NewGraphic := TGraphicclass(Value.Classtype).Create;

正确调用我的构造函数,一切都很好.

我想做类似的事情,我想克隆一个TGraphic:

procedure TForm1.button1Click(Sender: TObject);var   g1: TGraphic;   g2: TGraphic;begin   g1 := TMyBitmap.Create;   g1.LoadFromfile('C:\...\example.bmp');   //Image1.Picture.Graphic := g1;   g2 := TGraphicclass(g1.Classtype).Create;end;

除此之外从不调用我的构造函数,也不调用TBitmap构造函数.它只调用TObject构造函数.施工后:

g2.Classname: 'TMyBitmap'g2.Classtype: TMyBitmap

类型是正确的,但它不会调用我的构造函数,但其​​他地方的代码相同.

为什么?

即使在这个假设的人为例子中,它仍然是一个问题,因为TBitmap的构造函数没有被调用;内部状态变量未初始化为有效值:

constructor TBitmap.Create;begin  inherited Create;  Ftransparentcolor := clDefault;  FImage := TBitmAPImage.Create;  FImage.Reference;  if DDBsOnly then HandleType := bmDDB;end;

TPicture中的版本:

NewGraphic := TGraphicclass(Value.Classtype).Create;

反编译为:

mov eax,[ebp-]call TObject.Classtypemov dl,call DWord ptr [eax+
g2 := TGraphicclass(g1.Classtype).Create;
c]mov [ebp-
mov eax,ebxcall TObject.Classtypemov dl,call TObject.Createmov ebx,eax
c],eax

我的版本:

function CloneGraphic(Value: TGraphic): TGraphic;var    NewGraphic: TGraphic;begin   NewGraphic := TGraphicclass(Value.Classtype).Create;   Result := NewGraphic;end;

反编译为:

{ TMyGraphic }constructor TMyBitmap.Create;begin  inherited Create;    OutputDeBUGStringA('InsIDe TMyBitmap.Create');end;function CloneGraphic(Value: TGraphic): TGraphic;var    NewGraphic: TGraphic;begin    NewGraphic := TGraphicclass(Value.Classtype).Create;    Result := NewGraphic;end;procedure TForm1.button1Click(Sender: TObject);var    g1: TGraphic;    g2: TGraphic;begin    OutputDeBUGString('Creating g1');    g1 := TMyBitmap.Create;    g1.LoadFromfile('C:\Archive\-=Images=-\ChessvDanCheckmateIn38.bmp');    OutputDeBUGString(PChar('g1.Classname: '+g1.Classname));    OutputDeBUGStringA('Assigning g1 to Image.Picture.Graphic');    Image1.Picture.Graphic := g1;    OutputDeBUGString('Creating g2');    g2 := Graphics.TGraphicclass(g1.Classtype).Create;    OutputDeBUGString(PChar('g2.Classname: '+g2.Classname));    OutputDeBUGString(PChar('cloning g1 into g2'));    g2 := CloneGraphic(g1);    OutputDeBUGString(PChar('g2.Classname: '+g2.Classname));end;

更新一

将“克隆”推送到单独的功能:

ODS: Creating g1 Process Project2.exe (38)ODS: InsIDe TMyBitmap.Create Process Project2.exe (38)ODS: g1.Classname: TMyBitmap Process Project2.exe (38)ODS: Assigning g1 to Image.Picture.Graphic Process Project2.exe (38)ODS: InsIDe TMyBitmap.Create Process Project2.exe (38)ODS: Creating g2 Process Project2.exe (38)ODS: g2.Classname: TMyBitmap Process Project2.exe (38)ODS: cloning g1 into g2 Process Project2.exe (38)ODS: g2.Classname: TMyBitmap Process Project2.exe (38)ODS: g1.Classname: TMyBitmap Process Project2.exe (38)

没有帮助.

更新二

很明显,我清楚地提供了清晰的截图,清楚地显示了我的清晰代码,清楚地表明我清楚的代码显然是清楚的.很明显:

更新三

这是一个使用OutputDeBUGStrings的非官方版本:

Creating g1   InsIDe TMyBitmap.Createg1.Classname: TMyBitmapAssigning g1 to Image.Picture.Graphic   InsIDe TMyBitmap.CreateCreating g2g2.Classname: TMyBitmapcloning g1 into g2g2.Classname: TMyBitmapg1.Classname: TMyBitmap

原始结果:

TGraphic = class(TPersistent)...protected  constructor Create; virtual;...end;TGraphicclass = class of TGraphic;

格式化的结果:

更新四

我尝试关闭所有编译器选项:

注意:请勿关闭扩展语法.没有它,您无法分配函数的结果(未声明的标识符结果).

更新五

按照@DavID的建议,我尝试在其他一些机器上编译代码(所有Delphi 5):

> Ian Boyd(我):失败(windows 7 64位)
> Dale:失败(windows 7 64位)
>戴夫:失败(windows 7 64位)
>克里斯:失败(windows 7 64位)
> JamIE:失败(windows 7 64位)
>周杰伦:失败(windows XP 32位)
>客户构建服务器:失败(windows 7 32位)

Here’s the source.

解决方法 这似乎是一个范围问题(以下是来自D5 Graphics.pas):

你没有任何问题覆盖Create,并且当TGraphicclass(Value.Classtype)时没有任何问题.Create;从Graphics.pas单元中调用.

但是,在另一个单元TGraphicclass(Value.Classtype).Create;无法访问受保护的TGraphic成员.所以你最终调用了TObject.Create; (这是非虚拟的).

可能的解决方案

>编辑并重新编译Graphics.pas
>确保克隆方法子类位于层次结构的下方. (例如TBitmap.Create是公开的)

编辑:附加解决方案

这是获取对类的受保护成员的访问权的技术的变体.
不保证解决方案的稳健性,但似乎确实有效. 总结

以上是内存溢出为你收集整理的Delphi:构造不调用重写的虚拟构造函数全部内容,希望文章能够帮你解决Delphi:构造不调用重写的虚拟构造函数所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1268165.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存