集合對象通常透過枚舉器(IEnumVARIANT)實現訪問控制,但需定義複雜的複製策略與集合方法。若僅需簡單的索引訪問,介面陣列提供更輕量的替代方案。本文示範以介面陣列實作集合對象的完整範例。
| 角色 | 類別名 | 介面名 |
|---|---|---|
| 集合建立類 | CVoxSys | IVoxSys |
| 集合對象類 | CVoxChs | IVoxChs |
| 子對象類 | CVoxCh | IVoxCh |
CVoxCh:單一資料項
private:
BSTR m_bstrMessage;
CVoxCh() { m_bstrMessage = A2BSTR("No inited!"); }
Message (BSTR)
STDMETHODIMP CVoxCh::get_Message(BSTR* pVal) {
*pVal = m_bstrMessage;
return S_OK;
}
CVoxChs:管理子對象陣列
private:
CComPtr m_arrpCh[160]; // 子對象介面陣列
long m_nChs; // 實際子對象數
CVoxChs() { m_nChs = 0; }
// 新增子對象
[id(1), helpstring("method AddCh")] HRESULT AddCh([out, retval] long* pVal);
// 取得子對象數量
[propget, id(2), helpstring("property Count")] HRESULT Count([out, retval] long* pVal);
// 依索引取得子對象介面
[propget, id(3), helpstring("property Ch")] HRESULT Ch([in] long index, [out, retval] IVoxCh** pVal);
// AddCh:建立新子對象並加入陣列
STDMETHODIMP CVoxChs::AddCh(long* pVal) {
CVoxCh::CreateInstance(&m_arrpCh[m_nChs]);
m_nChs++;
*pVal = 0; // 回傳索引 0 (或可回傳實際索引)
return S_OK;
}
// get_Count
STDMETHODIMP CVoxChs::get_Count(long* pVal) {
*pVal = m_nChs;
return S_OK;
}
// get_Ch:透過 CComPtr::CopyTo 安全複製介面指標
STDMETHODIMP CVoxChs::get_Ch(long index, IVoxCh** pVal) {
return m_arrpCh[index].CopyTo(pVal);
}
關鍵點:CComPtr::CopyTo() 自動處理 AddRef(),確保呼叫端獲得有效介面指標。
CVoxSys:提供集合對象入口
private:
CComPtr m_spVoxChs;
FinalConstruct() 初始化集合對象
// 使用 FinalConstruct 因其可回傳標準 HRESULT
HRESULT CVoxSys::FinalConstruct() {
return CVoxChs::CreateInstance(&m_spVoxChs);
}
VoxChs
[propget, id(1), helpstring("property VoxChs")] HRESULT VoxChs([out, retval] IVoxChs** pVal);
STDMETHODIMP CVoxSys::get_VoxChs(IVoxChs** pVal) {
return m_spVoxChs.CopyTo(pVal);
}
AddCh() 新增子對象實例,再進行存取,符合一般程式設計邏輯。for each、IEnumVARIANT 相容性,仍應實作標準枚舉器。以介面陣列 (CComPtr<T>[]) 替代枚舉器,可大幅簡化集合對象實作:無需定義複製策略、無需實作 Next/Skip/Reset/Clone,只需 Add、Count、Item(index) 三個核心成員。配合 CComPtr 自動引用計數管理,代碼簡潔且安全。適用於內部工具、輕量級組件或原型開發。