可以在FreePascal中的变体记录的案例中复制标识符吗?

Kev*_*ith 7 pascal freepascal record variant

这是我的问题:我想创建一个记录类型,其中在变体记录的情况下,一些(但不是全部)将具有某个字段.根据维基,这是完全合法的.然而,当我尝试编译以下代码时:

program example;

{$mode objfpc}{$H+}

uses sysutils;

type
  maritalStates = (single, married, widowed, divorced);

  TPerson = record
    name: record
      first, middle, last: string;
    end;
    sex: (male, female);
    dob: TDateTime;
    case maritalStatus: maritalStates of
      single: ( );
      married, widowed: (marriageDate: TDateTime);
      divorced: (marriageDate, divorceDate: TDateTime;
        isFirstDivorce: boolean)      
  end;

var
  ExPerson: TPerson;

begin
ExPerson.name.first := 'John';
ExPerson.name.middle := 'Bob';
ExPerson.name.last := 'Smith';
ExPerson.sex := male;
ExPerson.dob := StrToDate('05/05/1990');
ExPerson.maritalStatus := married;
ExPerson.marriageDate := StrToDate('04/01/2015');

end.
Run Code Online (Sandbox Code Playgroud)

编译失败,出现以下错误:

$ fpc ex.pas
Free Pascal Compiler version 3.0.0 [2016/02/14] for x86_64
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Win64 for x64
Compiling ex.pas
ex.pas(19,18) Error: Duplicate identifier "marriageDate"
ex.pas(21,3) Error: Duplicate identifier "marriageDate"
ex.pas(35,4) Fatal: There were 2 errors compiling module, stopping
Fatal: Compilation aborted
Error: C:\lazarus\fpc\3.0.0\bin\x86_64-win64\ppcx64.exe returned an error exitcode
Run Code Online (Sandbox Code Playgroud)

维基是完全错的,还是我错过了什么?有没有办法达到我想要的效果?

Ale*_*sar 3

非常有趣的问题。我确信这是可能的。如果您将代码修改为:

..
married, widowed, divorced: (marriageDate: TDateTime);
divorced: (divorceDate: TDateTime; isFirstDivorce: boolean)
..
Run Code Online (Sandbox Code Playgroud)

它有效,但这不是您想要的结果。由于结婚日期和离婚日期相互重叠(如评论中所述!)

在此输入图像描述

这张图片取自“Pascal 用户手册(第 4 版)”,您可以看到变体部件具有相同的内存位置。

根据Pascal 用户手册(第 4 版)和“Turbo Pascal ISBN 3-89011-060-6”一书,您引用的wiki上描述的记录声明无效!

  1. 所有字段名称必须是不同的 - 即使它们以不同的变体出现。
  2. 如果变体为空(即没有字段),则形式为:C:()
  3. 字段列表只能有一个变体部分,并且它必须位于记录的固定部分之后。
  4. 变体本身可能包含变体部分;因此可以嵌套变体部分。
  5. 在记录类型中引入的枚举类型常量标识符的范围扩展到整个封闭块。

第 1 点与此处相关!《Turbo Pascal》一书建议的解决方案是对多次出现的字段名称使用唯一的前缀。

在你的情况下,你可能会像这样:

TPerson = record
    name: record
      first, middle, last: string;
    end;
    sex: (male, female);
    dob: TDateTime;
    case maritalStatus: maritalStates of
      single: ( );
      married, widowed: (marMarriageDate: TDateTime);
      divorced: (divMarriageDate, divorceDate: TDateTime;
        isFirstDivorce: boolean)      
  end;
Run Code Online (Sandbox Code Playgroud)

另一个解决方案是将已婚、离婚......定义为记录类型。

..
married       : (m: TMarried);
divorced      : (d: TDivorced);
..
Run Code Online (Sandbox Code Playgroud)

  • 在本例中,结婚日期和离婚日期相互“重叠”。如果您分配到 weddingDate,您将从离婚日期读取相同的日期。IOW,它们占用相同的内存位置。 (2认同)