首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++Builder TCollection 詳解:泛型集合容器的設計模式與元件編輯器整合

     編輯:關於C++

C++Builder TCollection 詳解:泛型集合容器的設計模式與元件編輯器整合

TCollection 是 VCL 中設計時可視化編輯的核心容器基類,支援同質項目集合的擁有權管理、持久化、Object Inspector 整合。所有標準元件的子項集合(TDBGridColumns、TStatusPanels、TListColumns 等)均繼承自它。本文深度解析其架構、關鍵 API、衍生類模式與自定義集合開發全流程。

類層次與核心契約

TObject
  └── TPersistent
        └── TCollection
              └── [用戶衍生類,如 TDBGridColumns]
TObject
  └── TPersistent
        └── TCollectionItem
              └── [用戶衍生項目類,如 TColumn]

核心契約:
1. TCollection 擁有項目所有權,負責 Create/Free。
2. 項目類必須繼承 TCollectionItem,並實作 Assign(TPersistent*) 以支援集合複製。
3. 集合類構造函數必須傳遞項目元類:new TMyCollection(__classid(TMyItem))。

標準 VCL 集合對照表

集合類項目類宿主元件
TDBGridColumnsTColumnTDBGrid
TStatusPanelsTStatusPanelTStatusBar
TListColumnsTListColumnTListView
THeaderSectionsTHeaderSectionTHeaderControl
TFieldDefsTFieldDefTDataSet
TIndexDefsTIndexDefTTable
TCoolBandsTCoolBandTCoolBar
TWebActionItemsTWebActionItemTWebDispatcher

核心 API 速查

成員類型說明
Count屬性 (r)項目數量
Items[int Index]屬性 (rw)下標訪問,返回 TCollectionItem*
ItemClass屬性 (r)項目元類 TMetaClass*
Add()方法尾部新增項目,返回項目指標
Insert(int Index)方法指定位置插入,返回項目指標
Delete(int Index)方法刪除並釋放項目
Clear()方法清空並釋放所有項目
Assign(TPersistent*)方法深度複製另一集合
BeginUpdate/EndUpdate方法凍結/解凍 UI 刷新,批量操作必用
FindItemID(int ID)方法按 TCollectionItem.ID 查找

自定義集合開發全流程

步驟 1:定義項目類

class TMyItem : public TCollectionItem {
    int FValue;
    AnsiString FName;
    __published:  // 僅 published 成員可在 Object Inspector 編輯
    __property int Value = { read=FValue, write=FValue, default=0 };
    __property AnsiString Name = { read=FName, write=FName };
public:
    virtual void Assign(TPersistent* Source) override {
        if (TMyItem* src = dynamic_cast<TMyItem*>(Source)) {
            Value = src->Value; Name = src->Name;
        } else inherited::Assign(Source);
    }
};

步驟 2:定義集合類

class TMyCollection : public TCollection {
public:
    __fastcall TMyCollection() : TCollection(__classid(TMyItem)) {}
    TMyItem* __fastcall Add() { return static_cast<TMyItem*>(inherited::Add()); }
    TMyItem* __fastcall Insert(int Index) { return static_cast<TMyItem*>(inherited::Insert(Index)); }
    __property TMyItem* Items[int Index] = { read=GetItem, write=SetItem };  // 強類型索引器
};

步驟 3:宿主元件整合

class TMyComponent : public TComponent {
    TMyCollection* FItems;
    __published:
    __property TMyCollection* Items = { read=FItems, write=SetItems };
protected:
    void __fastcall SetItems(TMyCollection* Value) { FItems->Assign(Value); }
public:
    __fastcall TMyComponent(TComponent* Owner) : TComponent(Owner) {
        FItems = new TMyCollection();
    }
    __fastcall ~TMyComponent() { delete FItems; }
};

步驟 4:註冊集合編輯器(可選)

// 在 Register() 函數中
RegisterPropertyEditor(__typeinfo(TMyCollection), TMyComponent, "Items",
    __classid(TCollectionPropertyEditor));  // 內建編輯器通常足夠
// 若需自定義對話框,繼承 TCollectionEditor 並覆寫 ShowCollectionEditor()

進階主題

  1. ID 語義:TCollectionItem.ID 為運行時唯一遞增整數,不等於 索引位置。插入/刪除不改變既有項目 ID,FindItemID 依賴此特性。
  2. 持久化流向:集合隨宿主元件 WriteComponent 序列化為 DFM,格式為 object Items: TMyCollection ... Items = < item ... > end。項目類 必須 正確實作 Assign 否則設計時複製/黏貼會丟失數據。
  3. 執行緒安全:TCollection 非執行緒安全。多執行緒訪問需外部鎖或改用 TThreadList + 自定義項目類。
  4. 效能:Add/Insert/Delete 為 O(n) 陣列平移。項目數 > 5000 時建議改用 std::vector<TMyItem*> + 手動管理,或實作鏈表版 TCollection。

避坑清單

  • ❌ 忘記在集合構造函數傳遞 __classid(TMyItem) → Add() 返回 TCollectionItem* 導致強轉崩潰。
  • ❌ 項目類未實作 Assign → Collection->Assign(other) 僅淺複製指標,雙重釋放崩潰。
  • ❌ 宿主元件析構時未 delete FItems → 內存洩漏(VCL 不自動釋放子物件)。
  • ❌ 直接 delete Items[i] → 破壞集合擁有權,改用 Delete(i) 或 Clear()。

TCollection 是 VCL「設計時可視化」能力的基石。掌握其擁有權模型、持久化協議與編輯器整合,你就能開發出像標準元件一樣在 Object Inspector 中流暢運作的自定義集合屬性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved