C++实现一个只能在堆(栈)上生成对象的类

C++实现一个只能在堆(栈)上生成对象的类

2019-10-23 10:16:20 逆鳞⁢ 阅读数 51更多

目录

只能在堆上生成对象的类

只能在栈上生成对象的类


在C++中,类的对象创建可以静态创建在栈区, 如A a;还可以动态创建在堆区,如A* ptr=new A;这两种方式是不同的, 具体来

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

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

只能在堆上生成对象的类

总的思路就是使其不能在栈上创建, 在堆上可以

思路一: 构造函数私有化

1. 不能让这个类在栈上创建, 由于在栈上创建对象要直接调用构造函数, 如果我们把构造函数私有化, 就 无法在栈上创建对象了 
2. 那么我们又如何在堆上创建对象呢, 由于创建对象必定要调用构造函数, 在我们不定义其他构造函数时, 我们已经将两个默认构造函数已经私有, 在类外肯定是调用不到构造函数,  我们只有定义一个公有的静态成员函数 ,在其内部用new在堆区创建对象并返回其指针, (这里有很难以理解的一点, 在静态成员函数中用new 创建一个对象时, 也会调用构造函数, 我们知道, 静态成员函数不能调用成员函数, 那么new是如何调到构造函数的呢? 这得从静态成员函数为什么不能访问成员函数说起, 每一个对象都有一个隐含的this指针, 访问成员函数实际上时通过this指针调用的, 而在构造函数调用前还没有实例化出对象, 也就没有this指针, 所以构造函数不需要this指针调用, 静态成员函数也就可以调用构造函数了), 这点解释通了

还值得注意的是,  还必须将拷贝构造私有化, 不然会出现 用堆上创建好的对象拷贝构造一个栈上的对象这种情况发生

上代码

class.h


 
  1. #pragma once

  2. class T1 {

  3. T1(int val):b(val) {

  4.  
  5. }

  6. T1(T1& x):b(x.b){

  7.  
  8. }

  9. public:

  10. int b;

  11. static T1* newT1_p(int val = 0) {

  12. return new T1(val);

  13. }

  14. static T1& newT1(int val = 0) {

  15. return *new T1(val);

  16. }

  17. };

测试入口main.cpp


 
  1. #include<iostream>

  2. #include"class.h"

  3. int main() {

  4. T1* t1_p = T1::newT1_p(10);

  5. cout << t1_p->b << endl;

  6. T1& t1 = T1::newT1(20);

  7. cout << t1.b << endl;

  8. system("pause");

  9. return 0;

  10. }

 运行结果 :

 

如果我们静态创建在栈上的话编译不过, 如下:


 
  1. #include<iostream>

  2. #include"class.h"

  3. using namespace std;

  4.  
  5. int main() {

  6. T1 t2;

  7. T1 t3(10);

  8. system("pause");

  9. return 0;

  10. }

 运行结果: 编译未通过, 原因是构造函数私有化, 无法在类外访问

 

思路二: 析构函数私有化

将析构函数私有化, 在栈上也就不能直接创建对象了, 因为编译器在编译时会进行检测,  那没有析构函数也是不行的, 我们还需要实现一个函数来调用私有的析构函数, (这个思路就比构造函数私有好理解多了)

上代码

class.h


 
  1. class T2 {

  2. ~T2() {

  3. delete this;

  4. }

  5. public:

  6. int b;

  7. T2(int val = 0) :b(val) {

  8.  
  9. }

  10. void Destroy() {

  11. this->~T2();

  12. }

  13. };

测试入口 main.cpp


 
  1. #include<iostream>

  2. #include"class.h"

  3. using namespace std;

  4.  
  5. int main() {

  6. T2* t2_p = new T2(10);

  7. t2_p = t2_p->Destroy();

  8. cout << t2_p->b << endl;

  9. system("pause");

  10. return 0;

  11. }

尝试在栈上创建


 
  1. #include<iostream>

  2. #include"class.h"

  3. using namespace std;

  4.  
  5. int main() {

  6. T2 a;

  7. T2 b(10);

  8. system("pause");

  9. return 0;

  10. }


只能在栈上生成对象的类

总体思路就是一个普通的类, 不让其在堆上创建对象, 在堆上创建对象必定要用到new ,那我们直接在这个类内部将new重载成一个私有的成员函数, 目的就是让在类外使用不到原来的操作符new, 这样在类外就无法在堆上创建这个对象了

上代码

class.h


 
  1. #pragma once

  2. class T3 {

  3. void* operator new(size_t val) {}

  4. public:

  5. int a;

  6. T3(int val = 0) :a(val) {

  7.  
  8. }

  9. };

测试入口main.cpp


 
  1. #include<iostream>

  2. #include"class.h"

  3. using namespace std;

  4.  
  5. int main() {

  6. T3 a;

  7. cout << a.a << endl;

  8. T3 b(10);

  9. cout << b.a << endl;

  10. system("pause");

  11. return 0;

  12. }

尝试用new在堆上创建


 
  1. #include<iostream>

  2. #include"class.h"

  3. using namespace std;

  4.  
  5. int main() {

  6. T3* p1 = new T3;

  7. T3* p2 = new T3(10);

  8. system("pause");

  9. return 0;

  10. }

运行结果: 创建不成功 

posted @ 2019-11-05 08:08  grj001  阅读(171)  评论(0编辑  收藏  举报