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

基於 STL 序列容器的通用集合類封裝實戰

     編輯:關於C語言

引言:容器選擇的兩難

在面向對象開發中,類型設計包含兩大核心:內部數據結構與多實例的存取操作。STL 提供了序列式容器與關聯式容器兩大陣營,前者如 vector、list、deque,後者如 set、map 等。選擇何種容器取決於應用場景:

  • 需快速隨機訪問 → vector
  • 需頻繁插入刪除 → list
  • 符合隊列模型 → deque
  • 高性能查找/插入/刪除 → 關聯容器或 hash_set/hash_map

但專案初期往往難以確定最終容器類型,若能提供一個通用封裝,允許開發者隨時切換底層容器且不修改業務代碼,將極大提升維護靈活性。

STLCollection 通用集合類設計

STLCollection 利用模板模板參數實現容器類型參數化,核心定義如下:

template<typename T,
         template<class T, class U> class C = std::vector,
         template<class T> class U = std::allocator>
class STLCollection : public C<T, U<T>>

三個模板參數分別代表:元素類型、容器模板、配置器模板。預設使用 std::vector 與 std::allocator。

核心特性

  1. 完整構造函數轉發:覆寫所有基類構造函數,支援迭代器範圍構造
  2. 統一索引介面:提供 add、insert、erase、set、get、front、back、is_empty 等通用操作
  3. 迭代器分類分發:利用 iterator_traits 的 iterator_category 標籤分發,針對隨機訪問迭代器與輸入迭代器分別實現高效算法
  4. 保留基類介面:通過 using base::erase/insert/front/back 保持原容器介面可見

關鍵實現:標籤分發優化

void insert(size_t index, const T& t) {
    insert_impl(index, t, 
        typename std::iterator_traits<typename base::iterator>::iterator_category());
}

void insert_impl(size_t index, const T& t, std::random_access_iterator_tag) {
    if (index < base::size())
        base::insert(base::begin() + index, t);  // O(1) 定位
}

void insert_impl(size_t index, const T& t, std::input_iterator_tag) {
    if (index < base::size()) {
        typename base::iterator it = base::begin();
        while (index--) ++it;  // O(n) 遍歷
        base::insert(it, t);
    }
}

同樣策略應用於 erase、get 等操作,確保在 vector/deque(隨機訪問)與 list(雙向迭代器)上均能發揮最佳性能。

實戰擴展:variant_collection

繼承 STLCollection<_variant_t>,封裝 COM 變體類型的多態插入:

class variant_collection : public STLCollection<_variant_t> {
    typedef STLCollection<_variant_t> base;
public:
    using base::add; using base::insert; using base::set;

    void add(int val) { add<int>(val); }
    void add(double val) { add<double>(val); }
    // ... 其他基本類型重載 ...

protected:
    template<typename T>
    void add(T val) { _variant_t var(val); base::add(var); }
    // insert/set 同理
};

此設計展示了通用集合類的強大擴展性:業務層可直接操作基本類型,底層自動轉換為 _variant_t 存儲。

使用示例

// 使用 vector(預設)
STLCollection<int> vecColl;
vecColl.add(1); vecColl.add(2, false);  // 尾部/頭部插入

// 切換為 list,僅修改模板參數
STLCollection<int, std::list> listColl;
listColl.insert(0, 42);  // 介面完全一致

// 使用 variant_collection
variant_collection varColl;
varColl.add(3.14);
varColl.add("Hello");
varColl.insert(0, 100);

總結

STLCollection 通過模板模板參數與標籤分發技術,實現了序列容器的統一抽象層。它不僅解決了容器選擇的猶豫問題,更為後續的性能調優、容器遷移提供了零成本切換能力。結合繼承擴展,可快速構建領域專用集合類型,是 C++ 泛型程式設計的經典實踐範例。

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