實現一個支持多態的容器體系:
Collection、List 為抽象基類(含純虛函數)。ArrayList、LinkedList 繼承 List。Stack、Queue 通過模板模板參數適配任意 Container(預設 SeqList)。class Animal { virtual void eat(); };
class Mammal : public virtual Animal { virtual void breathe(); };
class Winged : public virtual Animal { virtual void flap(); };
class Bat : public Mammal, public Winged { };
內存佈局:Bat 僅包含一份 Animal 子物件。編譯器通過 vbptr(虛基類表指針)在運行時定位共享基類,代價是對象體積增加指針、訪問多一次間接寻址。
class Collection {
public:
virtual ~Collection() = 0; // 純虛析構
virtual void add(Object*) = 0;
};
Collection::~Collection() {} // 必須提供定義!
鐵律:只要類含有虛函數,析構函數必須聲明為 virtual。純虛析構強制子類實現,且基類必須給出定義(否則鏈接錯誤)。
templateclass Container = SeqList> class Stack { Container _con; // 組合而非繼承 public: void push(const T& x) { _con.push_back(x); } void pop() { _con.pop_back(); } const T& top() const { return _con.back(); } };
Container 必須是接受單一類型參數的模板(如 SeqList、std::vector、std::deque),實現「策略模式」的編譯期綁定版本。
模板聲明與定義必須對編譯器可見。標準做法:
xxx.hpp(或 .inl 包含在 .h 末尾)。.cpp,避免「未定義引用」鏈接錯誤。| 現象 | 原因 | 修正 |
|---|---|---|
| Linker error: duplicate symbol | 同名函數在多個 .cpp 中實例化 | 改用 .hpp 一體化、或 inline、或顯式實例化 |
| Stack overflow | 遞歸深度過大 / 局部大對象 | 改迭代、用動態分配、增大棧大小 |
| 虛基類訪問錯誤 | 構造順序誤解(虛基類最先構造) | 最派生類構造函數初始化列表直接調用虛基類構造函數 |
std::vector/std::list 替換手寫容器,專注適配器邏輯。std::unique_ptr 管理元素所有權,避免裸指針洩漏。static_assert 檢查 Container 滿足所需接口(C++20 Concepts 更佳)。