有没有一种方法可以确定指针的类型?

3

假设我有以下类型和变量:

type

TMyStruct1 = record
  Int1        : Integer;
  Int2        : Integer;
  Str1        : String;
  Str2        : String;
end;
PMyStruct1 = ^TMyStruct1;

TMyStruct2 = record
  Int1        : Integer;
  Int2        : Integer;
  Str1        : String;
  Str2        : String;
end;
PMyStruct2 = ^TMyStruct2;

var

P1: PMyStruct1;
P2: PMyStruct2; 

我有一个接受指针作为参数的函数。有没有办法确定该函数是使用P1还是P2变量调用的?

类似于:

function DoSomething(P: Pointer);
begin
 //if  ??? Type(P) = PMyStruct1 ??? then ....


内省通常是解释性语言(Java、C#、Python)的特点。编译型语言(C++、Delphi)通常不会本地实现此功能。 - d-stroyer
不,你无法确定该函数是使用P1还是P2被调用的。 - RBA
2
你甚至无法确定你是否拥有一个有效的指针。 - Sertac Akyuz
顺便说一句,不要使用记录,考虑使用简单的类。您可以检查类实例的类型。 - Rudy Velthuis
如果您只需要变量的类型,则在某些限制下,可以使用泛型来实现。 - Vasek
1
@Vasek 不,情况并非如此。这个问题没有基于泛型的解决方案。 - David Heffernan
3个回答

4

有没有办法确定函数是使用P1还是P2变量调用的?

不,没有这样的办法。


4

您可以通过为结构添加“标准头”来实现这一点。在您的情况下,一个简单的字段指示您的结构类型就足够了。

const 
  STRUCT_1 = 1;
  STRUCT_2 = 2;
type

TMyStruct1 = record
  StructType  : Integer
  Int1        : Integer;
  Int2        : Integer;
  Str1        : String;
  Str2        : String;
end;
PMyStruct1 = ^TMyStruct1;

TMyStruct2 = record
  StructType  : Integer
  Int1        : Integer;
  Int2        : Integer;
  Str1        : String;
  Str2        : String;
end;
PMyStruct2 = ^TMyStruct2;

var

P1: PMyStruct1;
P2: PMyStruct2;

function DoSomething(P: Pointer);
begin
  case PInteger(P)^ of //points to StructType
    STRUCT_1 : ;
    STRUCT_2 : ;
  end;
end;

调用您的函数的人需要负责正确填充StructType字段。

作为一种向前兼容措施,您还可以添加一个“StructSize”字段,以防您最终需要每个结构的多个版本。

这种类型检查是“弱”的,因为无法保证指针属于正确的类型,它只检查它指向的前4个字节是否包含STRUCT_1或STRUCT_2。

如果您不能控制那些记录的定义,那就没有办法了。


"如果您无法控制这些记录的定义,那么您就会很倒霉。" - 一旦您超出了上下文,他就不再适用。例如,更改函数的定义以接受结构类型参数... - Sertac Akyuz
1
我的意思是,这个问题的答案显然是否定的。看起来这只回答了一个不同的问题。正如 @sertac 所说,如果你准备改变规则,那么你当然可以得到不同的答案。 - David Heffernan
@SertacAkyuz ...或者在那个点上,声明两个函数为 DoSomething1(P: Pointer)DoSomething2(P: Pointer) - Ken Bourassa
1
@DavidHeffernan 显然是可以的,但前提是需要满足一些条件。不幸的是,仅凭指针本身无法验证这些先决条件是否满足。我在这里描述的基本上就是 TObject 的 IS 运算符的工作原理。因此,虽然确定随机选择的指针的类型确实是不可能的(或者至少是极其不可靠的),但仅仅回答“否”对我来说感觉相当不完整。 - Ken Bourassa
你们两个都有合理的观点,所以我不能只接受一个答案。 - Georgi Bonchev
显示剩余2条评论

0
一个指针是一种变量,它可以存储一个内存地址或特殊的 nil 值。
它可以指向任何东西,无论是有效的还是无效的、已经被销毁的对象,变量,字符串中的第三个字符或另一个指针。
但是它只存储内存地址,没有其他的信息。无法通过内存地址了解类型。如果需要类型或其他信息,应该自己处理。
对于同构结构,一种方法是在结构的第一个字节中存储其类型或版本,然后在指针地址上指向匹配的 PStructureX,就像 Ken 的回答中所示。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接