C# 與 Java 皆提供關鍵字(如 sealed、final)直接宣告類別不可被繼承,C++ 標準雖無內建機制,但可利用「子類建構子會自動呼叫父類建構子/解構子」的特性,透過將基底類別的建構子與解構子設為 private,阻止衍生類存取,從而達到禁止繼承的效果。
衍生類實例化時,必須先建構其虛擬基底類別。若虛擬基底類別的建構子為私有,且衍生類未被宣告為友元,編譯器將報錯,導致繼承鏈中斷。
為方便使用,設計兩層模板結構:
template <typename TDerive, typename TProvider>
class CForbidDeriveProviderBase {
friend TDerive;
friend TProvider;
private:
CForbidDeriveProviderBase() {}
~CForbidDeriveProviderBase() {}
};
template <typename TDerive>
class CForbidDeriveProvider : virtual public CForbidDeriveProviderBase<TDerive, CForbidDeriveProvider<TDerive>> {
public:
CForbidDeriveProvider() {}
~CForbidDeriveProvider() {}
};
class CNoDerive : public CForbidDeriveProvider<CNoDerive> {
public:
CNoDerive() {}
~CNoDerive() {}
void Alert() { AtlMessageBox(NULL, _T("Alert")); }
};
嘗試繼承 CNoDerive:
class CSomeDerive : public CNoDerive {
public:
CSomeDerive() {}
~CSomeDerive() {}
};
因 CForbidDeriveProvider 以虛擬繼承自 CForbidDeriveProviderBase,CSomeDerive 建構時會直接嘗試呼叫基底的私有建構子,但非友元類別無法存取,導致編譯失敗,成功封鎖繼承。
此模式僅需從 CForbidDeriveProvider 衍生並傳入自身類別名稱即可使用,無需手寫虛擬繼承,極大降低使用門檻。