模板節省原始碼,但每個實例化產生獨立二進位代碼。非型別參數 (如大小) 或型別參數 (如 int/long 同樣佈局) 導致近似代碼重複,造成 Code Bloat:目標檔膨脹、指令快取局部性變差。
template<typename T, std::size_t n>
class SquareMatrix {
public:
void invert(); // 5x5 與 10x10 產生兩份幾乎相同代碼
};
template<typename T>
class SquareMatrixBase {
protected:
void invert(std::size_t matrixSize); // 共享單一實作
};
template<typename T, std::size_t n>
class SquareMatrix : private SquareMatrixBase<T> {
using SquareMatrixBase<T>::invert; // 避免隱藏
public:
void invert() { this->invert(n); } // 內聯呼叫基類版本
};
T,所有同 T 不同 n 共享 invert。private 繼承表達「為實現而繼承」非 is-a。this-> 解決模板基類名稱查找問題。方案:基類儲存指標與大小,衍生類決定配置策略 (陣列成員或堆上):
template<typename T>
class SquareMatrixBase {
protected:
SquareMatrixBase(std::size_t n, T* pMem) : size(n), pData(pMem) {}
void setDataPtr(T* ptr) { pData = ptr; }
private:
std::size_t size;
T* pData;
};
// 陣列成員版 (無動態配置,物件較大)
template<typename T, std::size_t n>
class SquareMatrix : private SquareMatrixBase<T> {
public:
SquareMatrix() : SquareMatrixBase<T>(n, data) {}
private:
T data[n*n];
};
// 堆上版 (物件小,需管理生命週期)
template<typename T, std::size_t n>
class SquareMatrix : private SquareMatrixBase<T> {
public:
SquareMatrix() : SquareMatrixBase<T>(n, 0), pData(new T[n*n]) {
this->setDataPtr(pData.get());
}
private:
boost::scoped_array<T> pData;
};
int/long、指標型別許多平台 int/long 位元寬度相同,vector<int> 與 vector<long> 成員函式代碼相同。所有指標型別二進位表示相同。解法:
void* 通用實作 (如標準庫 vector/list/deque)。基類引入指標成員會增加每個物件大小。若衍生類已有資料指標,產生冗餘。可重新設計消除,但會降低封裝性、複雜化資源管理 (指標是否需刪除?)。有時少量代碼重複反而更簡潔。
void* 層)。