1

是否可以使用 Rtti 确定 aTRttiMethod是标记为overload还是overrideabstract

提前致谢。

4

2 回答 2

2

重载:我认为没有 RTTI 标志,但您可以检查是否有多个同名方法。这并不完美,但它可能与您将获得的一样接近。

覆盖:首先,确保方法是虚拟的。(或动态或消息调度。)然后检查类的祖先是否有其他具有相同名称和 VirtualIndex 属性的方法。

摘要:在 rtti.pas 的实现部分的深处,带有一堆方法数据标志,称为mfAbstract,定义为1 shl 7;。没有引用这个的代码,但它是在编译器生成的 RTTI 中实现的。当您有该方法的 TRttiMethod 参考时,您可以像这样测试它:

IsVirtual := PVmtMethodExEntry(method.Handle).Flags and (1 shl 7) <> 0;

PVmtMethodExEntry 在TypInfo单元中声明,因此您需要使用它才能工作。

于 2010-10-10T03:41:16.630 回答
0

如果它仍然很重要......我这样检查:

1. function GetCloneProc: TRttiMethod;
2. var
3.   methods: TArray<TRttiMethod>;
4.   parameters: TArray<TRttiParameter>;
5. begin
6.   methods := BaseType.GetDeclaredMethods;
7.   for Result in methods do
8.   begin
9.     if (Result.MethodKind = mkProcedure) and (Result.Name = 'CloneTo') and
10.       (Result.DispatchKind = dkStatic) and not Result.IsClassMethod then
11.    begin
12.       parameters := Result.GetParameters;
13.       if (Length(parameters) = 1) and (parameters[0].Flags = [pfAddress]) and
14.         (parameters[0].ParamType.TypeKind = tkClass) and
15.         ((parameters[0].ParamType as TRttiInstanceType).MetaclassType = (BaseType as TRttiInstanceType).MetaclassType) then
16.         Exit;
17.     end;
18.   end;
19.   Result := nil;
20. end;

您应该注意第 10 行。虚拟或动态方法分别具有 DispatchKinddkVtabledkDynamic。因此,如果方法标记为abstract它必须具有其中之一。同时为了避免得到class static方法,我使用第二个条件:not TRttiMethod.IsClassMethod

另请参阅 System.Rtti:

TDispatchKind = (dkStatic, dkVtable, dkDynamic, dkMessage, dkInterface);

您可以自行决定处理此枚举。

关于“覆盖”:看TStream.Seek,也许你会在那里找到对你有用的东西。

关于“过载”:上面@mason-wheeler 的答案在这种情况下看起来相当不错。

于 2018-03-26T22:21:42.567 回答