C++特殊类设计

2024-05-13 1301阅读

温馨提示:这篇文章已超过371天没有更新,请注意相关的内容是否还可用!

目录

一.   设计一个类,不能被拷贝

二.   设计一个类,使其只能在堆上创建

2.1   方式一 

2.2   方式二

2.3   方式三

三.   设计一个类,使其只能在栈上创建

四.   单例模式(设计一个类,只能创建一个对象))

4.1   设计模式

4.2   单例模式

 4.2.1   饿汉模式

 4.2.2   懒汉模式


一.   设计一个类,不能被拷贝

拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝, 只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。

  • C++98

    在C++98中,我们需要将拷贝构造函数以及赋值运算符重载函数设为私有,并且只声明,不实现。

    class CopyBan
    {
        // ...
        
    private:
        CopyBan(const CopyBan&);
        CopyBan& operator=(const CopyBan&);
        //...
    };
    

     原因:

    (1)设置成私有:如果只声明没有设置成private,用户自己如果在类外定义了,就可以不 能禁止拷贝了

    (2)只声明不定义:不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写 反而还简单,而且如果定义了就不会防止成员函数内部拷贝了。

    C++特殊类设计

    •  C++11

      C++11扩展delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上

      =delete,表示让编译器删除掉该默认成员函数。

      class CopyBan
      {
          // ...
          CopyBan(const CopyBan&)=delete;
          CopyBan& operator=(const CopyBan&)=delete;
          //...
      };

      二.   设计一个类,使其只能在堆上创建

      2.1   方式一 

      只能在堆上创建,那么我们就只能通过申请资源的方式创建对象。

      首先我们要将构造函数私有化,拷贝构造以及赋值拷贝禁掉,来防止通过栈上的对象拷贝赋值或者直接在栈上创建对象来创建对象。在我们禁掉构造函数以及拷贝构造之后,可以不考虑赋值拷贝的问题,因为已经不可能通过直接构造或者拷贝来创建栈上对象了,而创建出的对象一定是CreateOnly函数创建的,即一定是堆上的,而赋值拷贝是针对已经有的对象,所以可以不考虑。

      C++特殊类设计

      那我们就要通过自己实现的CreateOnly函数来调用构造函数创建对象,并且将此函数加上static修饰,因为我们将构造函数私有化之后,是不能创建出对象的,就不能通过对象去调用CreateOnly函数,因此要加上static,这样直接用类域调用就行。

      //只能在堆上
      class Heaponly
      {
      public:
          static Heaponly* CreateOnly()//静态是因为不能通过构造函数构造对象,所以不能对函数进行引用
          {
              return new Heaponly;
          }
          Heaponly(const Heaponly& ho) = delete;
          Heaponly& operator=(const Heaponly& ho) = delete;
      private:
          Heaponly()
          {}
          int _x;
          int _y;
          vector _a;
      };
      int main()
      {
          //Heaponly h;
          Heaponly* hp = Heaponly::CreateOnly();
          return 0;
      }

      2.2   方式二

      如果有多种构造函数,则可以用可变参数模板:

      C++特殊类设计

      //只能在堆上
      class Heaponly
      {
      public:
          template
          static Heaponly* CreateOnly(Args... args)//静态是因为不能通过构造函数构造对象,所以不能对函数进行引用
          {
              return new Heaponly(args...);
          }
          Heaponly(const Heaponly& ho) = delete;//防止通过栈上的对象拷贝构造
          Heaponly& operator=(const Heaponly& ho) = delete;//防止通过栈上的对象赋值拷贝
      private:
        //构造私有化
          Heaponly()
          {}
          Heaponly(int x,int y)
              :_x(x)
              ,_y(y)
          {}
          int _x;
          int _y;
          vector _a;
      };
      int main()
      {
          //Heaponly h;
          //Heaponly* hp1 = new Heaponly;
          //Heaponly* hp = Heaponly::CreateOnly();
          Heaponly* hp1 = Heaponly::CreateOnly(1, 1);
          Heaponly* hp2(hp1);
          return 0;
      }

      2.3   方式三

      我们还可以通过把析构函数私有化来实现只能在堆上创建。

      这样只要是栈上创建的对象都会编译报错,因为无法调用其析构函数,但是指针却可以正常的开辟空间,那我们要如何释放空间呢,可以自己定义一个销毁函数来调用析构函数销毁对象。

      C++特殊类设计

      //只能在堆上创建还可以封掉析构函数
      class Heaponly
      {
      public:
          Heaponly()
          {}
          Heaponly(int x,int y)
              :_x(x)
              ,_y(y)
          {}
          void Destory()
          {
              delete this;
          }
      private:
          ~Heaponly()
          {
              cout Destory(); });
          return 0;
      }

      三.   设计一个类,使其只能在栈上创建

      只在栈上创建对象,也就是要禁止申请资源空间。就需要变换一下CreateOnly函数,通过调用拷贝构造来构造对象。

      并且还要禁掉new,在C++中,new是由operator new和构造函数组成的,那我们就得重载一个operator new函数,并且禁掉。

      operator new

      • 是C++中用于动态分配内存的内置运算符
      • 主要作用是分配一块连续的内存空间,以便在其中存储对象或数据
      • 可以被重载
        //只能在栈上
        class Stackonly
        {
        public:
            template
            static Stackonly CreateOnly(Args... args)//静态是因为不能通过构造函数构造对象,所以不能对函数进行引用
            {
                return Stackonly(args...);
            }
            Stackonly(const Stackonly& ho) = delete;
            Stackonly& operator=(const Stackonly& ho) = delete;
            //重载一个类专属的operator new
            void* operator new(size_t n) = delete;
        private:
            //构造私有化
            Stackonly()
            {}
            Stackonly(int x,int y)
                :_x(x)
                ,_y(y)
            {}
            int _x;
            int _y;
            vector _a;
        };
        int main()
        {
            Stackonly so1 = Stackonly::CreateOnly();
            Stackonly so2 = Stackonly::CreateOnly(1, 1);
            //如果是new的话就避免不了,就要封掉operator new
            //Stackonly* so3 = new Stackonly(so1);
            return 0;
        }

        也可以跟上面一样,把析构函数私有化,这样申请到的资源无法释放,也就不能在堆上创建对象。

        那么类似,delete跟new一样,是由operator delete和析构函数组成的。那么我们也可以重载一个operator delete函数并且禁掉。

        operator delete

        • 和operator new配套的运算符,用于释放动态分配内存的内置运算符
        • 通过传递要释放的内存块的指针,它将该内存块返回给系统或内存管理器,以便将其重新分配给其他用途
        • 允许重载
          void* operator delete(size_t n) = delete;

          四.   单例模式(设计一个类,只能创建一个对象))

          4.1   设计模式

          设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。

          设计模式目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化。

          4.2   单例模式

          一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。

           4.2.1   饿汉模式

          在饿汉模式中,单例实例是在main函数之前就被创建。

          因为只能有一个对象,所以拷贝构造函数以及赋值拷贝函数都要禁用,构造函数需要私有。

          并且要实现一个接口函数来返回一个对象,并且这个对象必须是static,因为返回的必须是全局的,而不是局部的。

          接口函数也要设计为static的,因为构造函数私有,不能通过对象调用,只能用类域调用。

          由于是预先实例化,所以在类中实例化就行。

          C++特殊类设计

          namespace hunger
          {
              //饿汉:从一开始(main之前)就创建对象
              //问题:
              //1、如果单例对象数据较多,构造初始化成本较高,那么会影响程序启动的速度,迟迟进不了main函数
              //2、多个单例类对象有初始化启动依赖关系,饿汉无法控制。假设:A和B两个单例,假设要求A先初始化,B后初始化,饿汉满足不了
              class Singleton
              {
              public:
                  static Singleton* GetInstance()
                  {
                      return &_sint;
                  }
                  void Print()
                  {
                      cout 
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]