這個問題已經被老生常談了,一共有2中方案,但是今天寫內部類時,想到另一種方案,通過內部類實現停止類繼承;
首先來回顧前兩種方案:
1、C++11語法,final關鍵字
1 class A1{ 2 public: 3 A1(){}; 4 ~A1(){}; 5 }; 6 7 class B1 final:public A1{//禁止B1被繼承 8 9 }; 10 11 class C1:public B1{//錯誤, 12 13 };
編譯情況:
2、構造函數私有化
2.1直接將構造函數私有化,這種方案有一個問題,只是達到禁止繼承的目的,但是該類也無法創造出自己的對象;
1 class A1{ 2 //public: 3 private: 4 int a; 5 A1(int b):a(b){}; 6 public: 7 ~A1(){}; 8 }; 9 10 class B1 :public A1{ 11 12 }; 13 14 15 16 int main(){ 17 A1 a1=new A1(6); 18 //B1 *b1=new B1(); 19 return 0; 20 }
編譯器提示類A1也無法創建出對象;
2.2利用友元,定義一個基類,將基類構造函數私有化
1 class B1; 2 3 class A1{ 4 //public: 5 private: 6 int b; 7 A1(int a):b(a){}; 8 ~A1(){}; 9 friend class B1; 10 public: 11 int get(){return b;}; 12 }; 13 14 class B1 :public A1{ 15 public: 16 B1(int a):A1(a){}; 17 }; 18 19 class C1:public B1{ 20 public: 21 C1(int a):B1(a){}; 22 }; 23 24 int main(){ 25 C1 b1(10); 26 cout<<b1.get()<<endl; 27 //C1 c1; 28 }
上述代碼,並不能防止B1被繼承,因為C1會調用B1的構造函數,而B1調用A1,然而B1是A1的友元類,所以代碼可以通過,輸出結果為10;
解決上述情況只需要成為虛基類即可,因為多個類繼承自同一個基類時,共享同一個基類,為了防止基類被多次初始化,基類的初始化任務必須由繼承體系中最底層的類完成;
修改完代碼:
1 class B1; 2 3 class A1{ 4 //public: 5 private: 6 int b; 7 A1(int a):b(a){}; 8 ~A1(){}; 9 friend class B1; 10 public: 11 int get(){return b;}; 12 }; 13 14 class B1 :public virtual A1{ 15 public: 16 B1(int a):A1(a){}; 17 }; 18 19 class C1:public B1{ 20 public: 21 C1(int a):B1(a){}; 22 }; 23 24 int main(){ 25 C1 b1(10); 26 cout<<b1.get()<<endl; 27 //C1 c1; 28 }
編譯時報錯:
3、內部類方案
class C { private: /* data */ int a; public: C(/* args */){}; C(/* args */int c):a(c){}; int get(){return a;} ~C(){}; }; class A{ public: class B:public C//內部類,當為public時可以被繼承, { private: /* data */ public: B(/* args */):C(0){}; explicit B(int b):C(b) {} ; ~B(){}; }; private: }; class D:public A::B{ public: D(int c):A::B(c){}; ~D(){}; }; int main(){ D d(10); cout<<d.get()<<endl; }
運行結果為:
將內部類訪問屬性私有化:
1 class A{ 2 public: 3 private: 4 class B:public C//內部類,當為public時可以被繼承, 5 { 6 private: 7 /* data */ 8 public: 9 B(/* args */):C(0){}; 10 explicit B(int b):C(b) {} ; 11 ~B(){}; 12 }; 13 14 };
編譯結果為:
只不過這一種方案,需要在內部類的外部類定義接口訪問內部類,屬實繁雜,不過這也是一種實現方案,示例代碼為;
1 class C 2 { 3 private: 4 /* data */ 5 int a; 6 public: 7 C(/* args */){}; 8 C(/* args */int c):a(c){}; 9 int get(){return a;} 10 ~C(){}; 11 }; 12 class A{ 13 private: 14 class B:public C//內部類,當為public時可以被繼承, 15 { 16 private: 17 /* data */ 18 public: 19 B(/* args */):C(0){}; 20 explicit B(int b):C(b) {} ; 21 ~B(){}; 22 }; 23 B b; 24 public: 25 A(int a):b(a){}; 26 int get(){return b.get();}; 27 }; 28 int main(){ 29 A a(10); 30 cout<<a.get()<<endl; 31 }
最后感謝博主:https://blog.csdn.net/renwotao2009/article/details/6596710