MFC 提供 CObList 儲存 CObject*,但缺乏型別安全。CTypedPtrList 範本可包裝任意指標型別,提供型別安全的 AddHead、AddTail、GetNext 等方法。本文示範定義資料節點類別、型別安全串列、管理類別與遍歷用法。
class CPartData : public CObject
{
DECLARE_SERIAL(CPartData)
public:
CPartData() {}
virtual ~CPartData() {}
int m_nID;
int m_nValue;
CString m_strName;
double m_dblScore;
};
IMPLEMENT_SERIAL(CPartData, CObject, 1)
typedef CTypedPtrList CPartList;
CObList、CPtrList)。
class CPartManager
{
public:
CPartManager() {}
~CPartManager() { Clear(); }
BOOL Add(int id, int val, LPCTSTR name, double score)
{
CPartData* p = new CPartData();
p->m_nID = id; p->m_nValue = val; p->m_strName = name; p->m_dblScore = score;
m_list.AddTail(p);
return TRUE;
}
void Clear()
{
POSITION pos = m_list.GetHeadPosition();
while (pos) delete m_list.GetNext(pos);
m_list.RemoveAll();
}
// 唯讀存取
const CPartList& GetList() const { return m_list; }
private:
CPartList m_list;
};
CPartManager mgr;
mgr.Add(1, 100, _T("Item A"), 95.5);
mgr.Add(2, 200, _T("Item B"), 88.0);
// 遍歷
POSITION pos = mgr.GetList().GetHeadPosition();
while (pos) {
CPartData* p = mgr.GetList().GetNext(pos);
TRACE(_T("ID=%d, Name=%s, Score=%.1f\n"), p->m_nID, p->m_strName, p->m_dblScore);
}
// 移除特定項目 (需手動刪除記憶體)
pos = mgr.GetList().GetHeadPosition();
POSITION prev = NULL;
while (pos) {
POSITION cur = pos;
CPartData* p = mgr.GetList().GetNext(pos);
if (p->m_nID == 1) {
mgr.GetList().RemoveAt(cur);
delete p;
break;
}
}
| 操作 | 方法 |
|---|---|
| 尾端新增 | list.AddTail(ptr) |
| 頭端新增 | list.AddHead(ptr) |
| 取得頭端位置 | POSITION pos = list.GetHeadPosition() |
| 取得下一項並前進 | list.GetNext(pos) |
| 取得尾端位置 | POSITION pos = list.GetTailPosition() |
| 取得上一項並後退 | list.GetPrev(pos) |
| 移除指定位置 | list.RemoveAt(pos) (需自行 delete) |
| 清空串列 | list.RemoveAll() (不 delete 物件!) |
| 計數 | list.GetCount() |
| 尋找指標 | list.Find(ptr) 回傳 POSITION |
CTypedPtrList **不負責**刪除指標指向的物件。delete 每個元素,否則記憶體洩漏。std::list> (C++11) 或自訂智慧指標包裝類別。