C++创建对象有两种方式,一种是静态的创建对象,一种是动态的创建对象。
静态创建对象:在编译期间就已经为对象分配了内存空间编译器自动调用构造函数
动态创建对象:程序在运行期间才为对象开辟空间
如果我们想要只能在堆上创建对象,可能我们会想到在类里把构造函数声明成为私有的,这样一来我们就不能在外面直接定义对象,以为系统无法调用构造函数了。
但此时如果我们直接在类外面创建对象,那么在new 的时候是先要调用构造函数的,那此时也无法创建对象了
因此我们需要一个公有的方法去new对象来。
那么提供这个接口的就只能是static修饰的静态成员函数,因为这个静态成员函数直接可以通过类名去调用它。
在static这个成员函数中我们可以new去创建一个对象,因为在类里面我们是可以调用构造函数的。
public:
static A* Create(int a)
{
return new A(a);
}
protected: //可以解决继承问题把访问属性设置成protected
A(int a)
:_a(a)
{
cout << "A()" << endl;
}
int _a;
};
void FunTest()
{
A *a = A::Create(10);
}
第二种方式是将析构函数声明成为私有
为什么将析构函数声明成为私有的就不能在栈上创建对象了?因为当对象在栈上创建对象,是编译器为我们分配内存的,并且我们知道构造函数和析构函数都是由编译器自动调用的,也就是编译器管理了我们的对象的生命周期,因此如果此时编译器不能去调用我们的析构函数,那么它就无法去管理这个对象的生命周期了,那么编译器就不会去为这个对象开辟栈上的空间了,其实不止是析构函数和构造函数编译器需要检查类型,只要是非静态的成员函数,编译器都会去进行检查。
class A
{
public:
A()
{
cout << "A()" << endl;
}
void Destroy()
{
delete this;
}
private:
~A()
{
cout << "~A() "<< endl;
}
};
void FunTest()
{
A *a = new A;
a->Destroy();
}
但是这两种方式我们可以合起来写成一种,因为既然你是只能在堆上去申请内存,那么你是由程序员主动申请,那么释放的时候也是由程序员主动释放。你使用Create()去创造,使用Destroy()去销毁
class A
{
public:
static A* Create(int a)
{
return new A(a);
}
void Destroy()
{
delete this;
}
protected: //可以解决继承问题把访问属性设置成protected
A(int a)
:_a(a)
{
cout << "A()" << endl;
}
~A()
{
cout << "~A() "<< endl;
}
int _a;
};
void FunTest()
{
A *a = A::Create(10);
a->Destroy();
}
还有将这里的构造和析构不定义成私有的是因为如果继承实现动态多态,那么你得将这里A类中的析构函数写成虚函数的形式,然后在派生类里重写虚函数,防止发生内存泄漏。(这里的内存泄漏指的是如果你使用基类的指向派生类的对象,最后在析构的时候如果你没有写成虚析构并且没有在派生类里重写,并且你在派生类里面申请了一段空间。但它默认对象类型是基类的,只会去析构基类里的空间,此时内存就会泄露)