• 学习 TList 类的实现[5]


    先来实现 TMyList.SetCapacity.

    马上会想到下面代码:
    procedure TMyList.SetCapacity(const Value: Integer);
    begin
      if FCapacity <> Value then
        FCapacity := Value;
    end;
    
    但这样是远远不够的, 关键是需要分配内存, 像这样: ReallocMem(数组的起点指针, 元素个数*元素大小);

    数组的起点指针即是 FList; 元素个数就是 SetCapacity 的参数: Value; 元素即是指针, Win32 指针的大小是 4 个字节, 因此可以写为: ReallocMem(FList, Value*4);

    在 Win64 下的指针还会是 4 个字节吗? 还是这样写稳妥些: ReallocMem(FList, Value*SizeOf(Pointer));

    把方法改写为:
    procedure TMyList.SetCapacity(const Value: Integer);
    begin
      if FCapacity <> Value then
      begin
        ReallocMem(FList, Value * SizeOf(Pointer));
        FCapacity := Value;
      end;
    end;
    
    这还不够, 如果用户设置的 Value 值大于了列表的最大许可值(MaxListSize)怎么办? 小于了当前的元素数也不行啊, 再改写:
    procedure TMyList.SetCapacity(const Value: Integer);
    begin
      if (Value < FCount) or (Value > MaxListSize) then
        Exit;
    
      if FCapacity <> Value then
      begin
        ReallocMem(FList, Value * SizeOf(Pointer));
        FCapacity := Value;
      end;
    end;
    
    莫名其妙地 Exit, 会让人摸不着头脑, 抛出个异常吧(使用异常类需要 uses SysUtils 单元), 譬如:
    if (Value < FCount) or (Value > MaxListSize) then
        raise Exception.Create('非法的数据');
    
    再具体点, 让异常说出非法数据到底是什么:
    if (Value < FCount) or (Value > MaxListSize) then
        raise Exception.CreateFmt('非法数据:%d', [Value]);
    
    TList 把抛出异常也做成了一个 Error 方法, 我们暂时就这样吧, 再次改写方法为:
    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;
    
    TMyList.SetCapacity 方法完成了, 现在完整的代码是:
    unit MyList;
    
    interface
    
    uses SysUtils; {异常类 Exception 声明在 SysUtils 单元}
    
    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
      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);
    begin
    
    end;
    
    end.
    
  • 相关阅读:
    窗体的扩展样式GWL_EXSTYLE用于SetWindowLong
    内存映射对于大文件的使用
    Delphi实现全局鼠标钩子
    全局键盘钩子(WH_KEYBOARD)
    实现拦截API的钩子(Hook)
    JBoss + EJB3 + MySql : 开发第一个EJB
    取PE文件的引入表和导出表
    Webbrowser中模拟连接点击(非鼠标模拟)
    打造无DLL版穿透防火墙Downloader
    Delphi 常用属性+方法+事件+代码+函数
  • 原文地址:https://www.cnblogs.com/del/p/1127577.html
Copyright © 2020-2023  润新知