關於C++停止類被繼承的方法


這個問題已經被老生常談了,一共有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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM