学习 TList 类的实现[6]
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]的更多相关文章
- 学习 TList 类的实现[4]
现在准备一步步地模拟 TList 类, 建立一个自己的 TMyList. 首先, 这个类中应该包括前面提到的那个 Pointer 数组(TPointerList)的指针(PPointerList): ...
- 学习 TList 类的实现[8]
现在准备建立 Items 数组属性; 在 public 区输入下面代码:property Items[Index: Integer]: Pointer; 执行 Shift+Ctrl+C 后的代码是: ...
- 学习 TList 类的实现[1]
最近整理了一些函数列表, 算是一个宏观的安排; 等以后再碰到一些函数时就可以放置的更有次序一些. 我对函数与类的理解是: 函数是一个功能模块, 类是一个更强大的功能模块; Delphi 已经提供了很多 ...
- 学习 TList 类的实现[2]
我原来以为 TList 可能是一个链表, 其实只是一个数组而已. 你知道它包含着多大一个数组吗? MaxListSize 个!MaxListSize 是 Delphi 在 Classes 单元定义的一 ...
- 学习 TList 类的实现[5]
先来实现 TMyList.SetCapacity. 马上会想到下面代码: procedure TMyList.SetCapacity(const Value: Integer); begin if ...
- 学习 TList 类的实现[3] - 不能回避的话题: 内存分配
在 Delphi 中, 几乎所有的类型都有对应的指针类型, 譬如: Char PChar Word PWORD Double PDouble TPoint PPoint 甚至一种类型对应这着几种指针类 ...
- 学习 TList 类的实现[7]
总结目前 TMyList 已具备的功能(3 个方法.3 个属性): Add: 添加; Delete: 删除; Clear: 清空;Count: 元素总数;Capacity: 已存在的所有元素位置数;L ...
- Java虚拟机JVM学习07 类的卸载机制
Java虚拟机JVM学习07 类的卸载机制 类的生命周期 当Sample类被加载.连接和初始化后,它的生命周期就开始了. 当代表Sample类的Class对象不再被引用,即不可触及时,Class对象就 ...
- Java虚拟机JVM学习04 类的初始化
Java虚拟机JVM学习04 类的初始化 类的初始化 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值. 在程序中,静态变量的初始化有两种途径: 1.在静态变量的声明处进行初始 ...
随机推荐
- 网站的PV UV IP---网站常见软件性能
IP,衡量不同时间段的上网人数.00:00-24:00内相同的地址被计算一次.例:日300W IP,至少300W人访问PV,衡量页面受欢迎程度.每刷新一次,被记录一次(刷pv),网站被访问的页面的数量 ...
- httpwebrequest异步参考
http://www.cnblogs.com/SanMaoSpace/archive/2011/07/27/2118133.html http://www.cnblogs.com/qianlifeng ...
- 【Android】10.4 卡片视图
分类:C#.Android.VS2015: 创建日期:2016-02-19 一.简介 Android 从5.0开始包含了一个全新的卡片视图小部件,这个新的小部件默认就像一张带有圆角和轻微阴影的白色卡片 ...
- jave web 开发中 遇到修改不生效的几部方法 总结
在web开发中经常遇到修改文件之后没有正确被加载的情况 1.重启服务器 2.结束多余 javaw.exe 进程 3.删除web容器下的缓存文件 work 4. ctrl+f5 强制刷新缓存,如果是 ...
- Makefile学习之路——4
变量的类别有递归扩展变量和简单扩展变量.只用一个“=”符号定义的变量被称为递归扩展变量.通过下面例子观察递归扩展变量的特点. .PHONY: all foo=$(bar) bar=$(ugh) ugh ...
- wpf treeview中的两个事件
使用模板HierarchicalDataTemplate <HierarchicalDataTemplate x:Key="BookMarkTemplate" > &l ...
- uart 超声波传感器数据读取
传感器选择 淘宝上搜索 US-100 , 价格大概在17块人民币左右. 读取数据的代码如下: // include/aplex_tty.h #ifndef _APLEX_TTY_H__ #define ...
- Hibernate- 条件查询
01.搭建开发环境 02.条件查询 package com.gordon.test; import java.util.List; import org.hibernate.Query; import ...
- Hibernate-使用事务
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletExcepti ...
- java-动态获取项目根路径
${ pageContext.request.contextPath } <hr> <a href="${ pageContext.request.contextPath ...