设计一个类
只能在堆上创建?
只能在栈上创建?
只能创建一个对象?(单例模式**)
C++中创建对象的方法有两种,静态创建和动态创建。
1.静态创建
静态创建是由编译器为对象在栈空间中分配一块内存,通过直接移动栈顶指针,取出需要多大的空间,然后再这块内存上钓调用构造函数形成一个栈对象。直接调用类的构造函数。
2.动态创建
通过new运算符将对象建立在堆空间中。首先,调用operator new()函数,在堆空间中找适合的内存并进行分配;然后,调用构造函数构造对象,初始化这块内存空间。间接调用类的构造函数。
限制对象只能在什么地方建立?
1.只能在堆上创建?
意思是不能静态的创建对象,即不能直接调用类的构造函数。只能动态创建对象,使用new操作符完成。
方法一:将构造函数设为私有。
想到这种办法的原因是,将构造函数设为私有后,无法再类外调用构造函数来创建对象,只能使用new运算符来建立对象。
但是这种方法是不可行的,因为new运算符执行的过程中有两步,调用operator new()函数,在堆空间中找适合的内存并进行分配。然后,调用构造函数构造对象,初始化这块内存空间。C++提供new运算符的重载,其实只允许重载operator new()函数,而operator函数用于分配内存,无法提供构造功能。
方法二:将析构函数声明为私有
将析构函数设置为私有的,就可以保证只能在堆上创建一个新的类对象,这样可以自由的控制对象的生命周期,但是徐亚提供创建和撤销的公共接口。
class B
{
public:
B() {}
void Destroy()
{
delete this;
}
private:
~B() {}
};
int main()
{
B *p = new B;
p ->Destroy(); // 如果类中没有定义Destroy()函数, 而在这里用"delete p;"代替"p->Destroy();", 则会报错. 因为"delete p;"会去调用类的析构函数, 而在类域外调用类的private成员函数必然会报错.
return 0;
}
C++是一个静态绑定的语言,在编译的过程中,所有的非虚函数调用都必须分析完成。即使是虚函数,也要检查可访问性。在栈上生成的对象,编译器会帮我们析构,所以析构函数需要访问,但是在堆上生成的对象,由于析构是由程序员自己决定的,所以不一定需要析构函数。
但是问题又出来了,将析构函数设置为私有,不仅仅会限制栈对象生成外,还回限制继承。如果一个类不作为基类,通常会将其构造函数声明为私有的。
方法三:为了限制栈对象,但不想限制继承,可以将析构函数声明为protected。
class B
{
protected:
~B() { }
public:
void destroy()
{
delete this ;//调用保护析构函数
}
};
但是,用new创建的一个对象,但不使用delete释放,而是用destory释放,不符合用户习惯,所以将构造函数也设置为私有或保护,让类提供一个静态成员函数专门用于生产该类型的堆对象。
即使用静态成员函数创建对象和销毁,将构造函数和析构函数声明为protected。(设计模式中的单例模式就是这么实现的)
class B{
protected:
B(){}
~B(){}
public:
static B* create(){
return new A();
}
static void destory(B* p){
delete p;
p = NULL;
}
};
2.只在栈上生成对象?
不能动态创建对象,即不能调用new操作符,可以将opterator new和operator delete设置为私有的。
//设计一个类只能在栈上创建对象, //不能调用new 操作符,重载operator new() 和 operator delete() class B {
private:
void * operator new(size_t size){}
void operator delete(void *ptr){}
public:
B(){}
~B(){}
};