[toc] C++ 中类对象的建立分为两种:静态建立和动态建立。

  • 静态建立: 由编译器为对象在栈空间上分配内存,直接调用类的构造函数创建对象,如
1
A a;
  • 动态建立:使用 new 关键字在堆空间上创建对象,底层首先调用 operator new() 函数,在堆空间上寻找合适的内存并分配;然后,调用类的构造函数创建对象。例如:
1
A *p = new A();

# 限制对象只能建立在堆上

  • 最直观的思想,避免直接调用类的构造函数,因为对象静态建立时,会调用类的构造函数创建对象,但也不能直接将构造函数设为私有,因为设为私有最后就只能使用 new() 的方法进行创建对象,而使用 new, 底层会直接调用构造函数

# 将析构函数设置为私有

静态对象建立在栈上,是由编译器分配和释放空间,所以编译器会在开始检查非静态函数,如果发现析构函数是私有的,则不会在栈中创建该对象 (因为无法自动释放),

1
2
3
4
5
6
7
8
9
10
11
class A{
public:
A(){}
void destroy(){
delete this;
}
private:
~A(){

}
};

产生的问题

用 new 的对象,无法 delete, 只能自己写一个 destroy 函数
无法解决继承问题,如果这个类是基类,就一定要设置析构函数为 virtual, 否则派生类无法析构

# 析构函数设置为 protected

构造函数设置为 protected , 并提供一个 public 的静态函数来完成构造,而不是在类的外部使用 new 构造,将析构函数设置为 protected

1
2
3
4
5
6
7
8
9
10
11
12
class A{
protected:
A(){}
~A(){}
public:
static A *create(){
return new A();
}
void destroy(){
delete this;
}
}

# 限制对象只能创建在栈上

# 将 operator new () 设置为私有

operator new() 设置为私有。原因:当对象建立在堆上事,是采用 new 的方式进行建立,其底层会调用 operator new() 函数,因此只要对该函数加以限制,就能防止建立在堆上

1
2
3
4
5
6
7
8
9
10
class A{
private:
//注意函数第一个参数和返回值都是固定的
void *operator new(size_t t){}
//重载了new就需要重载delete
void operator delete(void *ptr){}
public:
A(){}
~A(){}
};