加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Delphi:如何让几个虚方法链接到同一个函数?

发布时间:2020-12-15 09:21:23 所属栏目:大数据 来源:网络整理
导读:我有抽象迭代器类: TImageIterator = class (TObject) protected fCurLine,fCurPos: Integer; public //also basic constructors here,etc. function ReadNextPixel: Cardinal; virtual; abstract; function ReadNextAsGrayscale: Cardinal; virtual; abstr
我有抽象迭代器类:

TImageIterator = class (TObject)
  protected
    fCurLine,fCurPos: Integer;
  public
    //also basic constructors here,etc.
    function ReadNextPixel: Cardinal; virtual; abstract;
    function ReadNextAsGrayscale: Cardinal; virtual; abstract;
    function ReadNextSubpixel: Cardinal; virtual; abstract;
end;

和许多后代,比如T1BitImageIterator,T4BitImageIterator,T8BitImageIterator,T24BitRGBImageIterator.关键是要创建适合当前图像/像素格式的迭代器(在非矩形区域上),然后处理图像而不管其类型.

ReadNextPixel返回’原始像素数据’:1位图像中的0或1,8位图像中的0..255或24位RGB中的某种TColor.

ReadNextAsGrayscale返回0..255范围内像素的亮度,在8位图像的情况下,与ReadNextPixel相同.

ReadNextSubpixel与灰度/调色板图像中的ReadNextPixel相同,但返回R值,然后(在下一次调用中)G值,然后返回24位RGB图像中的B值.

现在我有这样的实现:

function T8BitImageIterator.ReadNextPixel: Cardinal;
begin
  Result:=fByteLine[fCurPos];
  inch(fCurPos);
  if fCurPos=fRight then begin
    //going to next scanline,checking for end of iterated area etc
  end;
end;

//another 'unique' functions

//code we'd be happy to get rid of
function T8BitImageIterator.ReadNextAsGrayscale: Cardinal;
begin
  Result:=ReadNextPixel;
end;

function T1BitImageIterator.ReadNextSubpixel: Cardinal;
begin
  Result:=ReadNextPixel;
end;

function T4BitImageIterator.ReadNextSubpixel: Cardinal;
begin
  Result:=ReadNextPixel;
end;

function T8BitImageIterator.ReadNextSubpixel: Cardinal;
begin
  Result:=ReadNextPixel;
end;

这些函数应尽可能快,因此额外的函数调用看起来很难看,但复制粘贴整个函数更糟糕!

我想做的是这样的事情:

T8BitImageIterator = class (TImageIterator)
    public
      function ReadNextPixel: Cardinal; override;
      function ReadNextAsGrayscale=ReadNextPixel; override;
      ...
  end;

但当然没有这样的语法.

它可以通过接口完成,但它们比虚函数调用要慢得多.此外,还可以定义

TReadNextPixelProc = function: Cardinal of object;

TImageIterator = class(TObject)
  ...
  public
    ReadNextAsGrayscale: TReadNextPixelProc;
    ...
 end;

然后在构造函数中初始化此变量,但这仍然有额外的成本,并使这些迭代器更难以使用(我们必须记住什么是TReadNextPixelProc等).

我们还可以加速函数调用:

function T8BitImageIterator.ReadNextAsGrayscale: Cardinal;
asm
  jmp ReadNextPixel;
end;

所以在执行ReadNextPixel之后我们不会回到ReadNextAsGrayscale,而是返回调用ReadNextPixel的地方.

但是所有这些解决方案似乎都不正确:我认为没有理由为什么2个VMT条目不能具有相同的函数指针,因此只有一个这个函数的副本被称为“任何其他名称”而无需额外成本.有可能这样做吗?

解决方法

声明一个执行工作的私有内联方法,并从三个虚方法中的每一个调用它.内联引擎有时不会生成最有效的代码,因此请通过检查生成的代码来检查它的执行方式.

这种方法复制了可执行文件中的代码,但避免在源代码中这样做.一个聪明的编译器/链接器可以删除这个重复,但Delphi工具从来没有这样的能力.破解VMT是完全可能的,但我个人不会那样做.我认为你不会获得明显的收益.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读