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

目录

只能在堆上生成对象的类

只能在栈上生成对象的类


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

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

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

只能在堆上生成对象的类

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

思路一: 构造函数私有化

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

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

上代码

class.h

#pragma once
class T1 {
	T1(int val):b(val) {

	}
	T1(T1& x):b(x.b){
		
	}
public:
	int b;
	static T1* newT1_p(int val = 0) {
		return new T1(val);
	}
	static T1& newT1(int val = 0) {
		return *new T1(val);
	}
};

测试入口main.cpp

#include<iostream>
#include"class.h"
int main() {
	T1* t1_p = T1::newT1_p(10);
	cout << t1_p->b << endl;
	T1& t1 = T1::newT1(20);
	cout << t1.b << endl;
	system("pause");
	return 0;
}

 运行结果 :

 

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

#include<iostream>
#include"class.h"
using namespace std;

int main() {
	T1 t2;
	T1 t3(10);
	system("pause");
	return 0;
}

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

 

思路二: 析构函数私有化

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

上代码

class.h

class T2 {
	~T2() {
 		delete this;
	}
public:
	int b;
	T2(int val = 0) :b(val) {
 
	}
	void Destroy() {
       this->~T2();
	}
};

测试入口 main.cpp

#include<iostream>
#include"class.h"
using namespace std;

int main() {
	T2* t2_p = new T2(10);
	t2_p = t2_p->Destroy();
	cout << t2_p->b << endl;
	system("pause");
	return 0;
}

尝试在栈上创建

#include<iostream>
#include"class.h"
using namespace std;

int main() {
	T2 a;
	T2 b(10);
	system("pause");
	return 0;
}


只能在栈上生成对象的类

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

上代码

class.h

#pragma once
class T3 {
	void* operator new(size_t val) {}
public:
	int a;
	T3(int val = 0) :a(val) {

	}
};

测试入口main.cpp

#include<iostream>
#include"class.h"
using namespace std;

int main() {
	T3 a;
	cout << a.a << endl;
	T3 b(10);
	cout << b.a << endl;
	system("pause");
	return 0;
}

尝试用new在堆上创建

#include<iostream>
#include"class.h"
using namespace std;

int main() {
	T3* p1 = new T3;
	T3* p2 = new T3(10);
	system("pause");
	return 0;
}

运行结果: 创建不成功 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值