文档章节

学习 TList 类的实现[4]

涂孟超
 涂孟超
发布于 2014/09/26 15:35
字数 1038
阅读 4
收藏 0
现在准备一步步地模拟 TList 类, 建立一个自己的 TMyList.

首先, 这个类中应该包括前面提到的那个 Pointer 数组(TPointerList)的指针(PPointerList):
TMyList = class(TObject)
  FList: PPointerList;
end;

 
 
 
 
 

 

 

  
既然是一个列表, 应该有 Count 字段:
TMyList = class(TObject)
  FList: PPointerList;
  FCount: Integer;
end;

 
 
 
 
 

 

 

  
TList 类还有一个 FCapacity 字段.

譬如当前列表中有 10 个元素时, 其实列表已经提前申请出更多位置, 这样就不必每次添加每次申请内存, 从而提高了效率.

这个 FCapacity 字段就表示已申请的可放置元素位置的总数.
TMyList = class(TObject)
  FList: PPointerList;
  FCount: Integer;
  FCapacity: Integer;
end;

 
 
 
 
 

 

 

  
它们都应该是私有的:
TMyList = class(TObject)
private
  FList: PPointerList;
  FCount: Integer;
  FCapacity: Integer;
public
end;

 
 
 
 
 

 

 

  
应该用属性操作它们:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
  end;
{--------------------------------}
  TMyList = class(TObject)
  private
    FList: PPointerList;
    FCount: Integer;
    FCapacity: Integer;
  public
    property Capacity: Integer; {光标放在属性上, 执行 Shift+Ctrl+C, 自动建立属性}
    property Count: Integer;
    property List: PPointerList;
  end;
{--------------------------------}

var
  Form1: TForm1;

implementation

{$R *.dfm}

end.

 
 
 
 
 

 

 

  
自动建立后的属性:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
  end;
{--------------------------------}
  TMyList = class(TObject)
  private
    FList: PPointerList;
    FCount: Integer;
    FCapacity: Integer;
    procedure SetCapacity(const Value: Integer);
    procedure SetCount(const Value: Integer);
    procedure SetList(const Value: PPointerList);
  public
    property Capacity: Integer read FCapacity write SetCapacity;
    property Count: Integer read FCount write SetCount;
    property List: PPointerList read FList write SetList;
  end;
{--------------------------------}

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TMyList }

procedure TMyList.SetCapacity(const Value: Integer);
begin
  FCapacity := Value;
end;

procedure TMyList.SetCount(const Value: Integer);
begin
  FCount := Value;
end;

procedure TMyList.SetList(const Value: PPointerList);
begin
  FList := Value;
end;

end.

 
 
 
 
 

 

 

  
在 TList 中, SetCount 和 SetCapacity 方法都是放在 protected 区以供子类使用, 这里暂时不考虑继承的问题, 就让它们先在 private 区吧;

不过 List 属性应该是只读的, 它就是那个核心数组的指针, 对它的赋值应该通过更多其他的方法.

修改如下:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
  end;
{--------------------------------}
  TMyList = class(TObject)
  private
    FList: PPointerList;
    FCount: Integer;
    FCapacity: Integer;
    procedure SetCapacity(const Value: Integer);
    procedure SetCount(const Value: Integer);
  public
    property Capacity: Integer read FCapacity write SetCapacity;
    property Count: Integer read FCount write SetCount;
    property List: PPointerList read FList;
  end;
{--------------------------------}

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TMyList }

procedure TMyList.SetCapacity(const Value: Integer);
begin
  FCapacity := Value;
end;

procedure TMyList.SetCount(const Value: Integer);
begin
  FCount := Value;
end;

end.

 
 
 
 
 

 

 

  
作为一个列表, 最起码应该有 Add、Delete、Clear 方法.

Add 方法的参数应该是一个指针(TList 就是存放指针的吗), 如果需要同时返回元素的位置, 应该定义成函数;

Delete 是删除指定位置上的元素, 参数是个位置号;

Clear 是清除列表, 对象释放(Destroy)时也应该执行此过程.

综上所述, 修改如下:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
  end;
{--------------------------------}
  TMyList = class(TObject)
  private
    FList: PPointerList;
    FCount: Integer;
    FCapacity: Integer;
    procedure SetCapacity(const Value: Integer);
    procedure SetCount(const Value: Integer);
  public
    destructor Destroy; override;         {覆盖父类的 Destroy 方法}
    function Add(Item: Pointer): Integer;
    procedure Clear;                      {在 TList 中这是个虚方法, 以备子类覆盖}
    procedure Delete(Index: Integer);
    property Capacity: Integer read FCapacity write SetCapacity;
    property Count: Integer read FCount write SetCount;
    property List: PPointerList read FList;
  end;
{--------------------------------}

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TMyList }

function TMyList.Add(Item: Pointer): Integer;
begin

end;

procedure TMyList.Clear;
begin

end;

procedure TMyList.Delete(Index: Integer);
begin

end;

destructor TMyList.Destroy;
begin
  Clear;     {在类释放时同时清除列表}
  inherited; {在 TList 中没有这句, 大概是因为它的父类也没什么可继承的}
end;

procedure TMyList.SetCapacity(const Value: Integer);
begin
  FCapacity := Value;
end;

procedure TMyList.SetCount(const Value: Integer);
begin
  FCount := Value;
end;

end.

 
 
 
 
 

 

 

  
为了让代码更清晰, 还是把这个类相关的所有代码放到一个独立的单元吧(新建一个单元, 我们把它保存为: MyList.pas).

因为 MaxListSize、TPointerList、PPointerList 都是在 Classes 单元定义的, 为了省略 uses Classes, 在 MyList 单元中重新做了定义.
unit MyList;

interface

const
  MaxListSize = Maxint div 16;

type
  PPointerList = ^TPointerList;
  TPointerList = array[0..MaxListSize - 1] 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

end;

procedure TMyList.Clear;
begin

end;

procedure TMyList.Delete(Index: Integer);
begin

end;

destructor TMyList.Destroy;
begin
  Clear;
  inherited;
end;

procedure TMyList.SetCapacity(const Value: Integer);
begin

end;

procedure TMyList.SetCount(const Value: Integer);
begin

end;

end.

 
 
 
 
 

 

 

  
至此, 类的轮廓已经出来, 该实现一下这些方法了.

本文转载自:http://www.cnblogs.com/del/archive/2008/03/28/1127265.html

共有 人打赏支持
涂孟超
粉丝 12
博文 2011
码字总数 14107
作品 0
深圳
程序员
私信 提问
VIM编辑器支持Python开发环境(Vim+Ctags+Taglist)

在Linux下用VI编辑器进行Python开发,有必要对VI编辑器进行一些配置,使其具备以下特性: 1、加强的 Python 语法高亮显示; 2、对脚本、项目生成 ctag 序列; 3、在 vim 中显示 ctag 序列列表...

庄小寒
2014/02/26
0
0
vim for php IDE 我的打造过程

vim是一个很强的神器,对于我只用到其中的一小部分内容,接下来是我打造 php IDE的全过程,希望有兄弟能指点我其中的不足,要学习的兄弟能跟我一起努力学习。 第一步:配_vimrc,配成自己喜欢...

路边拾草人
2011/04/16
9.7K
21
windows环境中vim插件配置(便利的vim)

打开vim的文件类型自动检测功能:filetype on,就是在vimrc文件中加上filetype on 1.ctags 1.1ctags功能: tags是个exe文件,在shell中执行来在工程目录中创建tags(就是函数的映射关系),适...

_FreeDoM
2014/06/04
0
0
Ubuntu下创建vim+Taglist+cscope+ctags组合编辑器

有人抱怨Linux系统下没有类似于VC之类的方便快捷的编辑器,有人用gedit, 有人用vim,但是都不方便而且也没有自动补全之类的方便用户的功能。本文简单介绍使用vim中的几个插件(Ctags、Cscop...

贪睡猫仙mosen
2014/06/17
0
0
[转]vim ctags使用方法

windows下很多人都使用source insight 编写和查看代码。linux下可以使用VIM,刚开始会觉得VIM像windows下的记事本,而如果使用得当,它并不比source insight 逊色。 在这里,我会尽我所能细致...

文艺小青年
2017/07/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

爬虫教程」Python做一个简单爬虫,小白也能看懂的教程

俗话说“巧妇难为无米之炊”,除了传统的数据源,如历史年鉴,实验数据等,很难有更为简便快捷的方式获得数据,在目前互联网的飞速发展写,大量的数据可以通过网页直接采集,“网络爬虫”应运...

糖宝lsh
今天
1
0
KEIL MDK工程中的宏定义:字符,值,字符串

下图中定义了2个宏: 等效于文件中: #define MCU_FLASH_LESSTHAN_64K #define VERSION_INFO_hw 'a' // MDK :VERSION_INFO_hw="'a'" 即MDK中的VERSION_INFO_hw="'a'" 和 #define VERS......

SamXIAO
今天
0
0
集合的最优子集划分

问题描述:如何将一个个数为n的集合N划分为为若干个子集N1…Nk,其中1≤k≤n,计算出每个子集的最优结果R1…Rk,使得F(R1…Rk)为最优的结果。 这个问题可以分成3步解决: 求出集合所有子集 ...

laolin23
今天
0
0
JavaScript实现在线Markdown编辑器、转换HTML工具-toolfk程序员工具网

本文要推荐的[ToolFk]是一款程序员经常使用的线上免费测试工具箱,ToolFk 特色是专注于程序员日常的开发工具,不用安装任何软件,只要把内容贴上按一个执行按钮,就能获取到想要的内容结果。T...

toolfk
今天
2
0
Source Tree 在git 密码更新后,无法拉取代码的解决办法

背景: git 密码总是需要修改。在修改代码后,拉去代码, source tree 总提示access denied. 解决方法:重新修改git 仓库对应的密码。 for mac:应用程序 -》 钥匙串 -》 搜索 source tre...

Carlyle_Lee
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部