ATL 大量運用 C++ 模板實現靜態多型、策略模式、智慧指標等核心機制,避免虛函數開銷。本文系統梳理 ATL 中關鍵的模板技術,並以可編譯範例逐一演示。
template <typename T>
T Max(const T& a, const T& b) { return a > b ? a : b; }
// 顯式指定模板參數
Max<int>(5, 'B'); // 回傳 66 ('B' 的 ASCII)
Max<char>(5, 'B'); // 回傳 'B'
// 類別模板:堆疊
template <typename T, int Size = 10>
class Stack {
T data[Size];
int top = 0;
public:
void Push(T v) { data[top++] = v; }
T Pop() { return data[--top]; }
};
Stack<int, 20> s; // 編譯期決定大小,無動態配置開銷
// 主模板
template <typename T> T Max(T a, T b) { return a > b ? a : b; }
// 針對 char* 特化:比較字串長度而非指標值
template <> char* Max<char*>(char* a, char* b) {
return strlen(a) > strlen(b) ? a : b;
}
// 類別模板特化
template <typename T> class Test { void F(T) { cout << "T version"; } };
template <> class Test<int> { void F(int) { cout << "int version"; } };
Test<char> t1; t1.F('A'); // T version
Test<int> t2; t2.F(10); // int version
ATL 中 CComQIPtr<T> 即為 CComPtr<T> 的特化版本,提供 QueryInterface 自動化。
struct Round1 { void Play() { cout << "Round1"; } };
struct Round2 { void Play() { cout << "Round2"; } };
template <typename Policy>
class Game {
Policy policy;
public:
void Play() { policy.Play(); }
};
Game<Round1> g1; g1.Play(); // Round1
Game<Round2> g2; g2.Play(); // Round2
ATL 的執行緒模型 (CComSingleThreadModel, CComMultiThreadModel) 即採此模式,編譯期決定同步策略,零虛函數開銷。
template <typename T>
class SmartPtr {
T* p;
public:
SmartPtr(T* ptr = nullptr) : p(ptr) {}
~SmartPtr() { if (p) p->Release(); }
T* operator->() { return p; }
T& operator*() { return *p; }
// 複製/移動語意需正确实现 (參考 CComPtr)
};
// 使用
SmartPtr<IUnknown> sp(pUnk);
sp->AddRef(); // 透過 operator-> 轉發
ATL 提供 CComPtr (單一介面) 與 CComQIPtr (自動 QI 多介面),完整實作參考計數、複製語意、附屬/分離語意。
template <typename Derived>
class Base {
public:
void DoSomething() {
static_cast<Derived*>(this)->Impl(); // 編譯期解析
}
};
class Derived : public Base<Derived> {
public:
void Impl() { cout << "Derived::Impl"; }
};
Derived d; d.DoSomething(); // 輸出 Derived::Impl,無虛函數表
ATL 大量使用 CRTP:
CComObject<T> 繼承自使用者定義的 T (class CComObject : public T),實現 COM 物件的建立/銷毀邏輯靜態綁定。CWindowImpl<T> 透過 ProcessWindowMessage 靜態分派訊息。| 特性 | CRTP (靜態多型) | 虛函數 (動態多型) |
|---|---|---|
| 多層繼承 | 中斷:MostDerived : Derived 會呼叫 Derived::Impl | 自然支援 |
| 基類指標容器 | 不可:Base<D1>* 無法指向 D2 | 可行:Base* 陣列存放不同衍生類 |
| 效能 | 零開銷,內聯優化 | 虛函數表查找、間接呼叫 |
| 程式碼膨脹 | 每個衍生類產生獨立程式碼 | 共享虛函數表 |