zoukankan      html  css  js  c++  java
  • 如何定一个只能在堆上或者只能在栈上定义的类

    C++中,对象的建立分为两种,一种是静态建立,如A a;另一种是动态建立,如 A *ptr=new A;

    静态建立:由编译器为对象在栈上分配内存,是通过直接移动栈顶指针,挪出适当的空间,然后在这片内存空间上调用构造函数形成一个栈对象,使用这种方法,直接调用类的构造函数

    动态建立:是通过new运算符将对象建立在堆空间中,这个过程分为两步,第一步是执行operator new()函数,在堆空间中搜索合适的内存并进行分配,第二步是调用构造函数构造对象,初始化这片内存空间,这种方法,间接调用类的构造函数

    接下来进行限制对象只能在那里建立?

    1.只能建立在堆上?

     就是不能静态的建立对象,即不能直接调用类的构造函数。

    分析:

    (1)我们容易想到将构造函数设为私有,在构造函数私有之后,无法在类外部调用构造函数来构造类对象,只能使用new运算符来建立对象,然而,前面已经说过,new运算符的执行过程分为两步,c++提供new运算符的重载,其实是只提供operator new() 函数,而operator()函数是进行内存分配的,无法提供构造功能,因此这种方法是不可以的

    (2)对象建立在栈上面时,是由编译器分配空间的,调用构造函数来构造栈对象,当对象使用完之后,编译器会调用析构函数来释放栈对象所占的空间,编译器管理了对象的整个生命周期,编译器为对象分配空间的时候,只要是非静态的函数都会检查,包括析构函数,但是此时析构函数不可访问,编译器无法调用类的析构函数来释放内存,那么编译器将无法在栈上为对象分配内存

    class a{
        public :
            a(){}
            void destory(){
                delete this;
            }
        private:
            ~a(){};
    }; 

       那可以尝试使用a  b;来建立对象,编译报错,提示析构函数无法访问,这样就只能使用new来创建对象,构造函数是共有的,可以直接调用,但是类中必须通过destory()函数来进行内存的释放,类对象使用完之后,必须调用destory()函数

       上述方法两个缺点:(1)无法解决继承问题,因为通常情况之下a作为基类,一般析构函数要设为vitual,然后子类重写,已实现多态,因此析构函数不能设为private,不过c++还有protected访问控制方式,将析构函数设置为protected,这样子类可以访问,但是类外无法访问。(2)使用不方便,不统一,因为你使用了new创造了对象,但是不能使用delete释放对象,必须使用destory函数,这种方式比较怪异,所以我们也可以将构造函数设置为protected,同时提供另一public static create()函数来进行替代new。这样  create()创建对象在堆上, destory()释放内存

    class a{
        public :
            static a* create(){
                return new a();
            }
            void destory(){
                delete this;
            }
        protected:
            a(){};
            ~a(){};
    }; 

    2.只能建立在栈上

       只有使用new操作符,才会使对象建立在堆上,因此只要禁用new操作符就可以了,所以我们将operator new()操作符设为保护或者私有就可以了

    class a{
        public :
            a(){};
            ~a(){};
        protected:
            void* operator new(size_t t){};  //重载new,注意参数以及返回值 
            void operator delete(void *ptr){};  //重载了new,就要重载delete 
            
    }; 
  • 相关阅读:
    XML(学习笔记)
    css样式学习笔记
    Request(对象)
    sql一些错误修改的总结
    转载(如何学习C#)
    sql server(学习笔记2 W3Cschool)
    sql sqrver(学习笔记1 W3Cschool)
    关于 flutter开发碰到的各种问题,有的已经解决有的一直没解决或者用其他方法替代
    关于 Flutter IOS build It appears that your application still contains the default signing identifier.
    关于 flutter本地化问题 The getter 'pasteButtonLabel' was called on null
  • 原文地址:https://www.cnblogs.com/jijiji/p/4862220.html
Copyright © 2011-2022 走看看