实现一个类只能在栈上创建对象
一个对象可以创建在栈上,堆上,全局区
创建对象的两种方式:
假设有一个Date类
Date d1; //静态创建一个对象
Date *d2=new Date; //动态创建一个对象
创建在栈上的对象
Date d1;//正常创建
Date d3(d1);//通过拷贝构造
创建在堆上的
Date *d2=new Date;
创建在全局区和静态区
std::Date d4;
static Date d5;
如果只能在栈上创建对象,就要将其他几种方式屏蔽。所以我们要将创建对象的方式固定为只能在栈上,并且其余方式不能创建对象,这些创建对象的方式都有一个共同的地方就是调构造,如果我们将构造函数私有化,只有通过特定的函数才能调用,那其他所有方式都无法创建对象。
new 在底层通过调用opertor new 和 构造,operator new 用于开空间,所以将operator new 私有,new将无法创建
- 构造函数私有化
断绝了所有创建方式,只能通过特定的函数创建对象
- 定义一个静态的获得对象的函数
为什么要是静态的?
因为类中的函数必须要通过一个对象进行调用,但是我们此时没有对象,要创建一个对象,所以只能将该函数声明成静态的,在类外直接访问。
具体如下:
1 #include <iostream>
2 using namespace std;
3 //只能在栈上为对象开辟空间,不能使用new
4 class InStack{
5 public:
6 static InStack GetStack()
7 {
8 InStack tmp;
9 return tmp;
10 }
11 void Print()
12 {
13 cout<<_a<<endl;
14 }
15 private:
16 int _a;
17 //构造私有化
18 InStack()
19 :_a(100)
20 {};
operator new(size_t size)=delete;//c++11特性,已删除函数,断绝所有访问路径
operator delete(size_t size)=delete;//如果仅私有的化,可以在类外定义,再通过友元,仍可以访问
21 };
22 //InStack p;//
23 //static InStack p5;//全局和静态都将无法调用构造
24 int main()
25 {
26 InStack p2=InStack::GetStack();
27 p2.Print();
28 /// InStack *p4=new InStack;
29 // InStack p3=p2;
30 // p3.Print();
31 return 0;
32 }
实现一个只能在堆上创建对象的类
只用通过new才能在堆上创建对象,所以只要将其他方式屏蔽即可
- 构造私有化
创建对象离不开调构造,将构造私有化后才能自定义创建对象的方式
- 定义一个静态的创建对象的函数
在函数中使用new
- 拷贝构造私有化
注意,拷贝构造创建的对象也是在栈上,所以如果通过一个在堆上的对象拷贝构造一个,还是会在栈上
具体代码
1 #include <iostream>
2 using namespace std;
3 //声明一个类只能在堆上
4
5 class HeapType{
6 public:
7 static HeapType* GetHeap() //无法用对象调用该函数,所以将其声明成全>
局的
8 {
9 HeapType* tmp=new HeapType; //在堆上开辟一块空间
10 return tmp;
11
12 }
13
14 void Print()
15 {
16 cout<<_a<<endl;
17 }
18 private:
19 int _a;
20 //私有化构造函数
21 HeapType()
22 :_a(10)
23 {};
24 //将拷贝构造私有化
25 HeapType(const HeapType& p)=delete;
26 };
27
28 int main()
29 {
30 HeapType* p=HeapType::GetHeap();//因为类中的函数必须使用对象调用,所以
要将GetHeap声明成静态成员函数,使其具有在类中具有全局性
31 p->Print();
32 // HeapType p2; 调用拷贝构造与构造函数时都会报错
33 // HeapType p3(p);
34 return 0;
35 }
36
在拷贝构造私有化时,如果在类外定义,再通过友元访问,也能访问私有,所以拷贝构造推荐使用已删除函数
linux 下支持c++11 使用 g++ -std=c++11 -o …进行编译