实现 TMyList.Add 函数.

TList 中的 Add 函数用到了一个 Grow 方法, 它的原理是元素越多就为以后准备更多内存, 我们这里省略为预留 4 个元素的内存;

TList 中的 Add 函数还同时触动了一个 Notify 方法, 这应该是为它们的子类准备的(估计是用它来激发一个事件的), 也不要了.


function TMyList.Add(Item: Pointer): Integer;
begin
  {如果预申请的内存用完了, 再申请够 4 个元素用的}
  if FCount = FCapacity then SetCapacity(FCapacity + );   {Add 是添加在最后面, 把指针赋予数组}
  FList^[FCount] := Item;   {函数返回}
  Result := FCount;   {元素总数 + 1}
  Inc(FCount);
end;

再实现 TMyList.Delete 过程.

同前, 把错误处理也简化成一个异常; 也省略了对 Notify 方法的触动.

其中用到了 System.Move, 可以参考: http://www.cnblogs.com/del/archive/2008/03/27/1126226.html

这里有一个问题是需要高度注意的: TList 在删除一个元素(它的元素就是指针)时, 并没有释放指针指向的对象, 只是从列表开除;
如果要同时 Free 掉对象, 应该使用 Contnrs 单元下的 TObjectList 类.


procedure TMyList.Delete(Index: Integer);
begin
  {如果给的 Index 不符合要求, 就抛出异常}
  if (Index < ) or (Index >= FCount) then
    raise Exception.CreateFmt('非法的 Index:%d', [Index]);   {删除的过程就是把当前元素后面的所有元素向前挪动一个位置}
  if Index < FCount then
    System.Move(FList^[Index + ], FList^[Index], (FCount - Index) * SizeOf(Pointer));   {总数 - 1}
  Dec(FCount);
end;

还要实现 TMyList.SetCount 方法.

之前我没有想到 Count 属性还是可写的; 这可够狠的, 譬如已经有 100 个元素, 如果让 Count := 1; 这一下就要删除后面 99 个元素!

还有不理解的是: 譬如已经有 100 个元素, 如果让 Count := 200; 那后面的 100 个元素即便是填充了空字符, 用指针读过来也不是对象啊? 觉得不妥. 不过暂时也这样了.


procedure TMyList.SetCount(const Value: Integer);
var
  i: Integer;
begin
  {如果参数非法, 抛出异常}
  if (Value < ) or (Value > MaxListSize) then
    raise Exception.CreateFmt('非法数据:%d', [Value]);   {如果预留内存不够, 马上申请}
  if Value > FCapacity then SetCapacity(Value);   {如果参数大于元素总数没有赋值的用空字符填充}
  {如果参数小于元素总数, 删除多余的元素      }
  if Value > FCount then
    FillChar(FList^[FCount], (Value - FCount) * SizeOf(Pointer), )
  else
    for i := FCount - downto Value do
      Delete(I);   {新的元素总数}
  FCount := Value;
end;

还有一个 TMyList.Clear 方法.

因为不用考虑列表中对象释放的问题, 这个就简单多了.


procedure TMyList.Clear;
begin
  SetCount();
  SetCapacity();
end;

至此, 已经声明的方法都实现了, 这个 TMyList 类也该能凑合使用了.

源码如下:


unit MyList;

interface

uses SysUtils;

const
  MaxListSize = Maxint div ; type
  PPointerList = ^TPointerList;
  TPointerList = array[..MaxListSize - ] of Pointer;   TMyList = class(TObject)
  private
    FList: PPointerList;
    FCount: Integer;
    FCapacity: Integer;
    procedure SetCapacity(const Value: Integer);
    procedure SetCount(const Value: Integer);
  public
    destructor Destroy; override;
    function Add(Item: Pointer): Integer;
    procedure Clear;
    procedure Delete(Index: Integer);
    property Capacity: Integer read FCapacity write SetCapacity;
    property Count: Integer read FCount write SetCount;
    property List: PPointerList read FList;
  end; implementation { TMyList } function TMyList.Add(Item: Pointer): Integer;
begin
  if FCount = FCapacity then SetCapacity(FCapacity + );
  FList^[FCount] := Item;
  Result := FCount;
  Inc(FCount);
end; procedure TMyList.Clear;
begin
  SetCount();
  SetCapacity();
end; procedure TMyList.Delete(Index: Integer);
begin
  if (Index < ) or (Index >= FCount) then
    raise Exception.CreateFmt('非法的 Index:%d', [Index]);   if Index < FCount then
    System.Move(FList^[Index+], FList^[Index], (FCount-Index)* SizeOf(Pointer));   Dec(FCount);
end; destructor TMyList.Destroy;
begin
  Clear;
  inherited;
end; procedure TMyList.SetCapacity(const Value: Integer);
begin
  if (Value < FCount) or (Value > MaxListSize) then
    raise Exception.CreateFmt('非法数据:%d', [Value]);   if FCapacity <> Value then
  begin
    ReallocMem(FList, Value * SizeOf(Pointer));
    FCapacity := Value;
  end;
end; procedure TMyList.SetCount(const Value: Integer);
var
  i: Integer;
begin
  if (Value < ) or (Value > MaxListSize) then
    raise Exception.CreateFmt('非法数据:%d', [Value]);   if Value > FCapacity then SetCapacity(Value);   if Value > FCount then
    FillChar(FList^[FCount], (Value - FCount) * SizeOf(Pointer), )
  else
    for i := FCount - downto Value do
      Delete(I);   FCount := Value;
end; end.

学习 TList 类的实现[6]的更多相关文章

  1. 学习 TList 类的实现[4]

    现在准备一步步地模拟 TList 类, 建立一个自己的 TMyList. 首先, 这个类中应该包括前面提到的那个 Pointer 数组(TPointerList)的指针(PPointerList): ...

  2. 学习 TList 类的实现[8]

    现在准备建立 Items 数组属性; 在 public 区输入下面代码:property Items[Index: Integer]: Pointer; 执行 Shift+Ctrl+C 后的代码是: ...

  3. 学习 TList 类的实现[1]

    最近整理了一些函数列表, 算是一个宏观的安排; 等以后再碰到一些函数时就可以放置的更有次序一些. 我对函数与类的理解是: 函数是一个功能模块, 类是一个更强大的功能模块; Delphi 已经提供了很多 ...

  4. 学习 TList 类的实现[2]

    我原来以为 TList 可能是一个链表, 其实只是一个数组而已. 你知道它包含着多大一个数组吗? MaxListSize 个!MaxListSize 是 Delphi 在 Classes 单元定义的一 ...

  5. 学习 TList 类的实现[5]

    先来实现 TMyList.SetCapacity. 马上会想到下面代码: procedure TMyList.SetCapacity(const Value: Integer); begin   if ...

  6. 学习 TList 类的实现[3] - 不能回避的话题: 内存分配

    在 Delphi 中, 几乎所有的类型都有对应的指针类型, 譬如: Char PChar Word PWORD Double PDouble TPoint PPoint 甚至一种类型对应这着几种指针类 ...

  7. 学习 TList 类的实现[7]

    总结目前 TMyList 已具备的功能(3 个方法.3 个属性): Add: 添加; Delete: 删除; Clear: 清空;Count: 元素总数;Capacity: 已存在的所有元素位置数;L ...

  8. Java虚拟机JVM学习07 类的卸载机制

    Java虚拟机JVM学习07 类的卸载机制 类的生命周期 当Sample类被加载.连接和初始化后,它的生命周期就开始了. 当代表Sample类的Class对象不再被引用,即不可触及时,Class对象就 ...

  9. Java虚拟机JVM学习04 类的初始化

    Java虚拟机JVM学习04 类的初始化 类的初始化 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值. 在程序中,静态变量的初始化有两种途径: 1.在静态变量的声明处进行初始 ...

随机推荐

  1. Linux系统中 Sublime Text 中文 GBK 文件乱码问题

    Sublime Text 是一个很不错编辑器,具有漂亮的界面和强大的功能.再加上丰富的插件,而且还跨平台,绝对是一款实打实的神器啊! 众所周知,Sublime Text 对中文支持的极差,可以说几乎就 ...

  2. 149. Best Time to Buy and Sell Stock【medium】

    Say you have an array for which the ith element is the price of a given stock on day i. If you were ...

  3. Along with all the above benefits, you cannot overlook the space efficiency and performance gains in using DataFrames and Dataset APIs for two reasons.

    Of all the developers’ delight, a set of APIs that makes them productive, that are easy to use, and ...

  4. 解决Xshell中文乱码问题

    文件====>属性==>中断===>编码===>选择utf8编码

  5. Android.util.Log 关于Android开发中打印log

    日常Android开发真机调试过程经常会遇到系统日志过多过快,想看的内容一闪而过的问题.而自定义些log可以很好的解决这些问题.   代码中添加 log  androidsdk中提供了log输出的ap ...

  6. Python内置字典;dict ,set

    dict and set dict:  键-值 /重复添加 set :  键 / key不能重复 对于不变对象来说,调用对象自身的任意方法,也不会改变该对象自身的内容.相反,这些方法会创建新的对象并返 ...

  7. activiti5.13工作流系列(一)-初识

    1.什么是工作流? 工作流就是让多个参与者之间按照某种预定义的规则传递文档.信息或任务的过程,工作流由实体(Entity).参与者(Participant).流程定义(Flow Definition) ...

  8. App.config 中读写appSettings、system.serviceModel终结点,以及自定义配置节

    转自:http://blog.csdn.net/chelen_jak/article/details/8190795 感觉写的很好,推荐

  9. smtpclient 邮件发送测试

    SmtpClient smtp = new SmtpClient(); //实例化一个SmtpClient smtp.DeliveryMethod = SmtpDeliveryMethod.Netwo ...

  10. iio adc转换应用编写

    #include <stdio.h>        #include <stdlib.h>         #include <fcntl.h>         # ...