如何定义一个只能在堆(栈)上生成对象的类
2017-07-08 11:34
176 查看
在C++中,类的对象建立分为两种,一种是静态建立,如A a;另一种是动态建立,如A* ptr=new A;
当然这两种方式是有区别的;
静态建立一个类对象,是由编译器在栈空间中开辟空间,是通过直接挪动栈顶指针,挪出适当的空间,
然后在这片内存空间,调用析构函数形成一个栈对象,使用这种方法直接调用类的构造函数;
动态建立一个类对象,是使用new运算符将对象建立在堆空间上的,这个过程分为两步,第一步是
调用operator new()函数,在堆空间中搜索合适的内存并进行分配,第二步是调用类的构造函数构造
对象,初始化这片空间,这种方法间接调用类的构造函数;
1.只能在堆上建立对象:
对象只能建立在堆上,那么就说明不能直接调用构造函数,所以我们可以想到将构造函数私有化,
但是这样也不行因为任意一种方法,都会调用类的构造函数;当对象建立在栈上,是由编译器为它
分配空间,当对象使用结束后,编译器会对它进行回收,由此可知编译器管理了它的整个生命周期;
如果我们私有化了析构函数,使编译器无法回收这块空间,那么编译器就不会在栈空间上开辟空间了;
这样就只能使用new操作符来建立对象,构造函数是公有的,可以直接调用,但是必须提供一个Destory
来进行内存空间的释放;类对象使用完成后必须使用Destory函数;
上述方法存在一个缺点:无法解决继承问题,如果A类作为其它类的基类,则析构函数通常设为virtual,
然后在子类中进行重写,以实现多态;因此析构函数不能设为private,可以将其设为protected:子类可以
访问,外部类不能访问;
另一个问题是,类的使用并不方便,使用new建立对象,却使用Destory函数释放对象,而不能使用
delete,(因为使用delete,delete对象的指针会调用析构函数,而析构函数类外不能访问);
因此,我们可以将构造函数设为protected:然后提供一个public的static函数完成构造,这样不使用new,
而是使用一个函数来构造,使用一个函数来析构;
这样调用Create函数在堆上创建A对象,调用Destory函数释放内存;
2.只能建立在栈上:
只有使用new操作符,对象才会建立在堆上,因此只要禁用new操作符,就可以实现类对象只能建立在
栈上。将operator new设为私有即可。
当然这两种方式是有区别的;
静态建立一个类对象,是由编译器在栈空间中开辟空间,是通过直接挪动栈顶指针,挪出适当的空间,
然后在这片内存空间,调用析构函数形成一个栈对象,使用这种方法直接调用类的构造函数;
动态建立一个类对象,是使用new运算符将对象建立在堆空间上的,这个过程分为两步,第一步是
调用operator new()函数,在堆空间中搜索合适的内存并进行分配,第二步是调用类的构造函数构造
对象,初始化这片空间,这种方法间接调用类的构造函数;
1.只能在堆上建立对象:
对象只能建立在堆上,那么就说明不能直接调用构造函数,所以我们可以想到将构造函数私有化,
但是这样也不行因为任意一种方法,都会调用类的构造函数;当对象建立在栈上,是由编译器为它
分配空间,当对象使用结束后,编译器会对它进行回收,由此可知编译器管理了它的整个生命周期;
如果我们私有化了析构函数,使编译器无法回收这块空间,那么编译器就不会在栈空间上开辟空间了;
class A { public: A() {} void Destory() { delete this; } private: ~A() {} private: int _a; }; void TestA() { A* a = new A; a->Destory(); }
这样就只能使用new操作符来建立对象,构造函数是公有的,可以直接调用,但是必须提供一个Destory
来进行内存空间的释放;类对象使用完成后必须使用Destory函数;
上述方法存在一个缺点:无法解决继承问题,如果A类作为其它类的基类,则析构函数通常设为virtual,
然后在子类中进行重写,以实现多态;因此析构函数不能设为private,可以将其设为protected:子类可以
访问,外部类不能访问;
另一个问题是,类的使用并不方便,使用new建立对象,却使用Destory函数释放对象,而不能使用
delete,(因为使用delete,delete对象的指针会调用析构函数,而析构函数类外不能访问);
因此,我们可以将构造函数设为protected:然后提供一个public的static函数完成构造,这样不使用new,
而是使用一个函数来构造,使用一个函数来析构;
class A { public: static A* Create() { return new A; } void Destory() { delete this; } private: A() {} ~A() {} private: int _a; }; void TestA() { A* a = A::CreateObj(); a->Destory(); }
这样调用Create函数在堆上创建A对象,调用Destory函数释放内存;
2.只能建立在栈上:
只有使用new操作符,对象才会建立在堆上,因此只要禁用new操作符,就可以实现类对象只能建立在
栈上。将operator new设为私有即可。
class A { public: A() {} ~A() {} private: void* operator new(size_t t) {} void operator delete(void* ptr) {} private: int _a; }; void TestA() { A a; }
相关文章推荐
- 如何定义一个只能在栈上生成对象的类
- 第二讲:如何定义一个只能在堆上生成对象的类
- 如何定义一个只能在堆上(栈上)生成对象的类?
- 如何定义一个只能在堆上(栈上)生成对象的类?
- 如何定义一个只能在栈上生成对象的类
- 如何定义一个只能在堆上(栈上)生成对象的类?
- 如何定义一个只能在堆上(栈上)生成对象的类?
- 如何定义一个只能在栈上生成对象的类
- 如何定义一个只能在堆上(栈上)生成对象的类
- 如何定义一个只能在堆上(栈上)生成对象的类?
- 如何定义一个只能在堆上(栈上)生成对象的类
- 如何定义一个只能在堆上生成对象的类
- 如何定义一个只能在栈/堆上生成对象的类
- 如何定义一个只能在栈上生成对象的类
- 如何定义一个只能在堆上(栈上)生成对象的类?
- 如何定义一个只能在堆上(栈上)生成对象的类?
- 如何定义一个只能在堆或者栈上生成的对象
- 如何定义一个只能在堆上生成对象的类
- 如何定义一个只能在堆上生成对象的类
- 如何定义一个只能在堆(栈)上创建对象的类