实现 TMyList.Add 函数.

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

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


function TMyList.Add(Item: Pointer): Integer;
begin{如果预申请的内存用完了, 再申请够 4 个元素用的}if FCount = FCapacity then SetCapacity(FCapacity + 4);{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 < 0) or (Index >= FCount) thenraise Exception.CreateFmt('非法的 Index:%d', [Index]);{删除的过程就是把当前元素后面的所有元素向前挪动一个位置}if Index < FCount thenSystem.Move(FList^[Index + 1], 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);
vari: Integer;
begin{如果参数非法, 抛出异常}if (Value < 0) or (Value > MaxListSize) thenraise Exception.CreateFmt('非法数据:%d', [Value]);{如果预留内存不够, 马上申请}if Value > FCapacity then SetCapacity(Value);{如果参数大于元素总数没有赋值的用空字符填充}{如果参数小于元素总数, 删除多余的元素      }if Value > FCount thenFillChar(FList^[FCount], (Value - FCount) * SizeOf(Pointer), 0)elsefor i := FCount - 1 downto Value doDelete(I);{新的元素总数}FCount := Value;
end;

还有一个 TMyList.Clear 方法.

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


procedure TMyList.Clear;
beginSetCount(0);SetCapacity(0);
end;

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

源码如下:


unit MyList;interfaceuses SysUtils;constMaxListSize = Maxint div 16;typePPointerList = ^TPointerList;TPointerList = array[0..MaxListSize - 1] of Pointer;TMyList = class(TObject)privateFList: PPointerList;FCount: Integer;FCapacity: Integer;procedure SetCapacity(const Value: Integer);procedure SetCount(const Value: Integer);publicdestructor 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;
beginif FCount = FCapacity then SetCapacity(FCapacity + 4);FList^[FCount] := Item;Result := FCount;Inc(FCount);
end;procedure TMyList.Clear;
beginSetCount(0);SetCapacity(0);
end;procedure TMyList.Delete(Index: Integer);
beginif (Index < 0) or (Index >= FCount) thenraise Exception.CreateFmt('非法的 Index:%d', [Index]);if Index < FCount thenSystem.Move(FList^[Index+1], FList^[Index], (FCount-Index)* SizeOf(Pointer));Dec(FCount);
end;destructor TMyList.Destroy;
beginClear;inherited;
end;procedure TMyList.SetCapacity(const Value: Integer);
beginif (Value < FCount) or (Value > MaxListSize) thenraise Exception.CreateFmt('非法数据:%d', [Value]);if FCapacity <> Value thenbeginReallocMem(FList, Value * SizeOf(Pointer));FCapacity := Value;end;
end;procedure TMyList.SetCount(const Value: Integer);
vari: Integer;
beginif (Value < 0) or (Value > MaxListSize) thenraise Exception.CreateFmt('非法数据:%d', [Value]);if Value > FCapacity then SetCapacity(Value);if Value > FCount thenFillChar(FList^[FCount], (Value - FCount) * SizeOf(Pointer), 0)elsefor i := FCount - 1 downto Value doDelete(I);FCount := Value;
end;end.

转载于:https://www.cnblogs.com/shijiaoyun/p/3844510.html

学习 TList 类的实现[6]相关推荐

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

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

  2. 如何学习streamdecoder类_如何学习篇5:强化2种能力——2种学习模式之运动类:隐性学习...

    [本文摘要] [注]本文所述内容为学习Yjango<学习观>相关视频之后的总结,观点归Yjango所有,本文仅作为学习之用. 阅读本节,会让你对英语这类运动类知识的学习豁然开朗,你会知道英 ...

  3. java中蛇的属性有哪些_学习Java类的属性

    学习Java类的属性-武汉北大青鸟 Public.private.protected显示了三种类中的属性和服务的类型,public是可以随意访问的.private是外界不能访问的(显示了数据的封装性) ...

  4. 普通话测试软件测分准吗,普通话学习测试类 | 普通话测试APP,能做到测试、学习提高两不误吗?...

    原标题:普通话学习测试类 | 普通话测试APP,能做到测试.学习提高两不误吗? 普通话是如今人们生活的常用语言,但要说到参加普通话测试,如果没有提前了解普通话测试的形式与要求,也不知道自己普通话的起步 ...

  5. 学信息安全买计算机,大学学习计算机类信息安全方向真的很蠢吗?

    大学学习计算机类信息安全方向真的很蠢吗? 本人2018届高考党,目前水平可以上一个不错的211,望借自主招生冲击985院校. 几天前,当我对老师说:"我目前最优先的选择是计算机-信息安全方向 ...

  6. java虚拟机预先加载哪些类_Java虚拟机JVM学习02 类的加载概述

    Java虚拟机JVM学习02 类的加载概述 类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对 ...

  7. Java为枚举类创建成员变量_Java学习——枚举类

    Java学习--枚举类 摘要:本文主要介绍了Java的枚举类. 部分内容来自以下博客: https://www.cnblogs.com/sister/p/4700702.html https://bl ...

  8. 2020-用多通道卷积神经网络学习单类特征用于人脸表现攻击检测

    2020年,Anjith George等人,期刊:TIFS,CCFA刊,Learning One Class Representations for Face Presentation Attack ...

  9. 游戏策划学习:类银河恶魔城、烬

    游戏策划学习:类银河恶魔城.烬 1.roguelike和银河恶魔城类游戏的区别 (1).地图复用是银河恶魔城类非常重要的一个特征.通过剧情导向和收集要素,让玩家多次探索同一个地图区域,用有限的资源延长 ...

最新文章

  1. 递推DP UVA 1366 Martian Mining
  2. [leetcode] Pow(x, n)
  3. Android被逼学习例子2
  4. 常见多媒体文件格式及视音频编解码总结
  5. qt编译器5.12.3怎么一次性删除所有的断点
  6. emmet插件使用(Css)
  7. SSIS Dataflow使用存储过程不能检索列名
  8. 论文解读丨基于局部特征保留的图卷积神经网络架构(LPD-GCN)
  9. Vmware和Citrix各自发展史
  10. Head First 设计模式 —— 工厂模式与工厂方法
  11. eclipse导入wsdl文件_Eclipse+Axis使用WSDL文件生成Web Service服务端/客户端
  12. Ubuntu 安装Chromium浏览器
  13. PLM与ERP的区别
  14. 客户端到服务器端的通信过程及 原理图很好
  15. 吴恩达深度学习02-3.567 Batch Normalization(BN)
  16. 李飞飞在谷歌开发者大会宣布谷歌AI中国中心正式成立
  17. 关于解决win10重装后右键单击一直转圈的问题
  18. Treap + FHQ Treap
  19. php 获取文件夹下面的文件列表和文件夹列表
  20. ABAP WB01 BDC ”No batch input data for screen “ ”没有屏幕 的批输入数据“

热门文章

  1. js动态添加的元素,动作绑定
  2. 目标检测(Object Detection)综述--R-CNN/Fast R-CNN/Faster R-CNN/YOLO/SSD
  3. TimingWheel[时间轮]介绍
  4. (05)VHDL实现分频器
  5. 1006.arm 板中杀死进程
  6. python制作一个简单的udp聊天器
  7. .net 反编译_向.net/Unity 程序员推荐一个十分因吹斯听的网站:sharplab.io
  8. vector容器动态申请内存的过程_记录一次自定义Allocator profile的过程
  9. Linux基本命令介绍
  10. nginx基础概念(100%)之connection