zoukankan      html  css  js  c++  java
  • 关于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

  • 相关阅读:
    maven scope 作用域
    MySQL数据库时区问题导致java程序无法连接数据库
    详细地址正则表达式
    java 重新学习 (七)
    .NET 多平台应用 UI介绍
    WPF关键帧动画
    RFID EPC Gen2 搜索模式和会话
    Razor 常用语法介绍
    Blazor 数据验证(6)
    Blazor 路由与页面导航(5)
  • 原文地址:https://www.cnblogs.com/cutelife/p/14821495.html
Copyright © 2011-2022 走看看