type 
  TRect = record
  case Integer of
    0: (Left, Top, Right, Bottom: Integer);
    1: (TopLeft, BottomRight: TPoint);
end;
这里的case语句完成什么任务啊?0和1又是哪来的啊?

解决方案 »

  1.   

    变体记录啊,相当于C语言中得Union。
      

  2.   

    一个记录类型能拥有变体部分,它看起来就像case 语句,在声明中,变体部分必须跟在其它字段的后面。
    要声明一个变体记录,使用下面的语法:
    type recordTypeName = record
    fieldList1: type1;
    ...
    fieldListn: typen;
    case tag: ordinalType of
    constantList1: (Variant1);
    ...
    constantListn: (Variantn);
    end;
    声明的前面部分(直到关键字case )和标准记录类型一样,声明的其余部分(从case 到最后一个可选的
    分号,)称为变体部分,在变体部分
    z tag 是可选的,它可以是任何有效标志符。如果省略了tag ,也要省略它后面的冒号(:)。
    ordinalType 表示一种有序类型。
    每个constantList 表示一个ordinalType 类型的常量,或者用逗号隔开的常量序列。在所有的常量
    中,一个值不能出现多次。
    每个Var i an t 是一个由逗号隔开的、类似于fieldList: type 的声明列表,也就是说,Var i a nt 有下面
    的形式:
    fieldList1: type1;
    ...
    fieldListn: typen;
    这里,每个fieldList 是一个有效标志符,或是由逗号隔开的标志符列表,每个type 表示一种类型,
    最后一个分号是可选的。这些类型不能是长字符串、动态数组、变体类型或接口(都属于动态管
    理类型),也不能是包含上述类型的结构类型,但它们可以是指向这些类型的指针。
    变体记录类型语法复杂,但语义却很简单:记录的变体部分包含几个变体类型,它们共享同一个内存区
    域。你能在任何时候,对任何一个变体类型的任何字段读取或写入,但是,当你改变了一个变体的一个ഊData types, variables and constants
    字段,又改变了另一个变体的一个字段时,你可能覆盖了自己的数据。如果使用了tag ,它就像记录中
    非变体部分一个额外的字段,它的类型是ordinalType 。
    变体部分有两个目的。首先,假设你想创建这样一个记录:它的字段有不同类型的数据,但你知道,在
    一个(记录)实例中你永远不需要所有的字段,比如:
    type
    TEmployee = record
    FirstName, LastName: string[40];
    BirthDate: TDate;
    case Salaried: Boolean of
    True: (AnnualSalary: Currency);
    False: (HourlyWage: Currency);
    end;
    这里的想法是,每个雇员或者是年薪,或者是小时工资,但不能两者都有。所以,当你创建一个TEmployee
    的实例时,没必要为每个字段都分配内存。在上面的情形中,变体间的唯一区别在于字段名,但更简单
    的情况是字段拥有不同的类型。看一下更复杂的例子:
    type
    TPerson = record
    FirstName, LastName: string[40];
    BirthDate: TDate;
    case Citizen: Boolean of
    True: (Birthplace: string[40]);
    False: (Country: string[20];
    EntryPort: string[20];
    EntryDate, ExitDate: TDate);
    end; type
    TShapeList = (Rectangle, Triangle, Circle, Ellipse, Other);
    TFigure = record
    case TShapeList of
    Rectangle: (Height, Width: Real);
    Triangle: (Side1, Side2, Angle: Real);
    Circle: (Radius: Real);
    Ellipse, Other: ();
    end;
    对每个记录类型的实例,编译器分配足够的内存以容纳最大变体类型的所有字段。可选的tag 和
    constantLists (像上面例子中的Rectangle 、Triangle 等)对于编译器管理字段没有任何作用,它们只是为
    了程序员的方便。
    使用变体记录的第二个原因是,你可以把同一个数据当作不同的类型进行处理,即使在编译器不允许类
    型转换的场合。比如,在一个变体类型中,它的第一个字段是64 位实数,在另一个变体类型中,第一个
    字段是32 位整数,你可以把一个值赋给实数(字段),然后再当作整数来读取它的前32 位值(比如,把
    它传给一个需要整数参数的函数)。
      

  3.   

    知道overload吗?这个和那个差不多。记录接受两种格式的数据保存。一种是四个整数,另一种是两个点类型。在C中也有这样的联合。
    其实,0和1是没有什么意义的,由编绎器根据传入的值来决定存储的类型。
      

  4.   

    有一点明白,我做了如下工作。case的哪个部分都能使啊?
    如何指定用case中的哪个部分?
    var
     rect:TRect;
     p:TPoint;
    begin
     rect.Top := 0;
     p.x := 0;
     p.y := 0;
     rect.TopLeft := p;
    end;
      

  5.   

    //计算机里一切都是数据~~
    //类型描述的是数据的存储方式~~
    //两种类型同时使用同一空间~~
    //这就是联合类型~~procedure TForm1.Button1Click(Sender: TObject);
    type
      TPointerInteger = record
        case Boolean of
          False: (rPointer: Pointer);
          True: (rInteger: Integer);
      end;
    type
      TByteChar = record
        case Boolean of
          False: (rByte: Byte);
          True: (rChar: Char);
      end;
    var
      vPointerInteger: TPointerInteger;
      vByteChar: TByteChar;
    begin
      vPointerInteger.rPointer := Self;
      ShowMessage(IntToStr(vPointerInteger.rInteger));
      vByteChar.rChar := 'A';
      ShowMessage(IntToStr(vByteChar.rByte));
    end;
    一个Integer占用4个字节
      (Integer----------------------------)
      |XXXXXXXX|XXXXXXXX|XXXXXXXX|XXXXXXXX|一个TPoint占用2 * 4 = 8个字节
      (TPoint.X: Integer------------------) (TPoint.Y: Integer------------------)
      |XXXXXXXX|XXXXXXXX|XXXXXXXX|XXXXXXXX| |XXXXXXXX|XXXXXXXX|XXXXXXXX|XXXXXXXX|一个TRect占用2 * 4 * 2个字节
      (TRect.TopLeft: TPoint----------------------------------------------------)
      (TRect.Left: Integer----------------) (TRect.Top: Integer-----------------)
      |XXXXXXXX|XXXXXXXX|XXXXXXXX|XXXXXXXX| |XXXXXXXX|XXXXXXXX|XXXXXXXX|XXXXXXXX|  (TRect.BottomRight: TPoint------------------------------------------------)
      (TRect.Right-----------------------)  (TRect.Bottom-----------------------)
      |XXXXXXXX|XXXXXXXX|XXXXXXXX|XXXXXXXX| |XXXXXXXX|XXXXXXXX|XXXXXXXX|XXXXXXXX|
    不要想的太复杂~~反正都离不开0和1~~ rect.TopLeft := p; //相当于rect.Top := p.x;rectLeft := p.Y
      

  6.   

    噢~
    我明白了,我觉得应该这样解释----
    这只是提供了用不同的方式访问同一块内存的方式,或是说同一块内存数据可以用多种形式体现!
    针对我的问题,就是对于TRect中存储的数据,我即可以通过Top、Left...对其进行访问,也可以用TopLeft或BottomRight进行访问。
    不知我理解的对否?