2011-04-04 88 views
8

假設有一種用於防止從派生類的一些正當的理由下去,Bjarne的給出瞭解決方案here的答案,「我能阻止人們從我的類派生?」簡單的「防止派生類」,在C++

但是,我認爲:

class final { 
protected: 
    final() { }   // line 3 
}; 

class B : private virtual final { 
}; 

class D : public B { // line 9 
}; 

int main() { 
    B b; 
    D d;    // line 14 
} 

當嘗試編譯,得到:

foo.cpp: In constructor ‘D::D()’: 
foo.cpp:3: error: ‘final::final()’ is protected 
foo.cpp:9: error: within this context 
foo.cpp: In function ‘int main()’: 
foo.cpp:14: note: synthesized method ‘D::D()’ first required here 

我是否對所有情況的解決方案的工作?恕我直言,這是更好的,因爲類final是通用的,並不需要預先知道類阻止派生。

回答

6

的解決方案是相當糟糕的,它可以與CRTP得到改善(土坯這樣做),但它不會是一個完整的解決方案。與您的代碼的問題是,不希望打破你的合同還有程序員(她是一個很好的人),但不知道她不應該派生從你的類可能想從她自己的類派生鎖定其他:

class YourSealedClass : private virtual final {}; 
class HerSealedClass : public YourSealedClass, private virtual final { 
}; 

注意,竟然沒有惡意的意圖,而本合同被打破。與CRTP的改進是:

template <typename T> 
class seal 
{ 
protected: 
    seal(){} 
    ~seal(){} 
}; 
class YourSealedClass : private virtual seal<YourSealedClass> {}; 

這將趕上前面的錯誤,因爲她的代碼將是:

class HerSealedClass : public YourSealedClass, private virtual seal<HerSealedClass> {}; 

當她不從seal<YourSealedClass>繼承編譯器將捕獲它。

這種方法的問題是,它不會阻止寫一些頑固(或惡性)程序員:

class MalignClass : public YourSealedClass, private virtual seal<YourSealedClass> {}; 

成爲國內密封類的子類,併爲自己的類這樣的增益訪問。

在C++ 0x中我相信(將不得不重新檢查的話),他們將提高一個模板不能交好模板參數的限制,這將是一個很好的一步成一類泛型類型安全解決方案這種方法(目前不可用)的優點是因爲構造函數和析構函數是私有的,所以只有朋友才能實例化類型。由於您使用的是CRTP爲從通過自己的類型作爲參數的具體實例繼承,你是在告訴只有你實際上可以實例化基地編譯器,以及所有作品的權利水到渠成。

+0

不是所有構造函數是在解決方案中私人!您忘記了由編譯器公共複製構造函數自動生成的內容。讓它也是私人的。你可以使用'seal '的公共拷貝構造函數來破解你的解決方案!我準備了類似C++ 03問題的答案:請參閱http://stackoverflow.com/a/12139218/1463922。 – PiotrNycz 2012-08-27 09:22:26

2

嘗試:

class D : public B, public virtual final 
{ 
};