结论:析构函数设为私有且在单例类的内部维护一个Chelper类。(如果是单例,还要将构造函数设为私有,如果是可以在全局有多个实例但是希望只能提供new创建,则构造必须公有且必须提供成员函数来调用delete this 来调用该对象的析构函数)。具体细节可看代码解释部分。
代码实现:
test.h
class annimal
{
public:
static annimal* getinstance()//只能访问静态成员变量,故将m_instance声明为静态变量
{
if (m_instance == NULL) {//保证全局只有这一个对象
m_instance = new annimal();
}
return m_instance;
}
private:
annimal() {
cout << "annimal 构造" << endl;
}
~annimal() {
cout << "annimal析构函数" << endl;
}
static void releseInstance() {
if (m_instance != NULL) {
annimal* tmp = m_instance;
m_instance = NULL;
delete tmp;
}
}
class CHelper {
public:
CHelper() {
annimal::getinstance();//加这行,表示在main之前构造,否则需要在main中调用getinstance才能new,这不太好。我们希望在main中调用getianstance 时走的是m_instance !=NULL returnm_instance 这代码,即不在main里面new.而是在main之前new
cout << "helper构造函数" << endl;
}
~CHelper() {
cout << "helper析构" << endl;
annimal::releseInstance();
}
};
static annimal* m_instance;
static CHelper m_helper;
};
test.cpp
annimal* annimal::m_instance = NULL;
annimal::CHelper annimal::m_helper;
main.cpp
annimal* pannimal= annimal::getinstance();
代码解释:
1.只能New来创建
必须将析构函数设置为私有,对外提供静态成员函数getinstance和静态成员变量m_instance.并在cpp中定义(因为静态成员变量必须要在类外定义)。且这里的New不是在main函数里面new.
2.实现自动释放
因为new出来的对象必须显示调用delete 操作符才能调用到该对象的析构函数,而要实现自动调用delete,必须只能在类内定义静态成员函数调用delete ,因为析构函数为私有,在类外不能调用delete.
现在问题转化为怎么自动调用该函数,即releseInstance,实现方式就是在定义一个帮助类,帮助类析构时调用releseInstance函数。那么帮助类什么时候析构呢?我们可以用帮助类声明一个在全局数据区的对象,即 static CHelper m_helper ,且静态变量必须初始化->所以在cpp中,annimal::CHelper annimal::m_helper。
通过上面的步骤,实现了单例类在main 函数之前构造,在main函数结束后析构(因为m_helper为全局的静态变量,程序结束时就自动调用到m_helper的析构函数,该析构函数调用带调用releseInstance自动释放单例对象)。
3.关于如何使用显示的New得到多个对象。(即在main中使用new annimal 而不是 getinstance 函数)
上面代码通过getinstance 得到对象,我们并没有在main中显示调用new,那我要如果需要得到多个对象(即不是单例),但只能通过New来创建这些对象,我们应该怎么实现呢?显示调用new应该怎么写呢。
1.在test.h添加成员函数destory并将构造函数设置为公有。
public:
annimal() {
cout << "annimal 构造" << endl;
}
void destory()
{
delete this;
}
2.在main.cpp中,使用new出来的对象必须显示调用destory函数,才能将ani对象析构,(且使用new必须将构造函数声明为共有的才能new)。且此时对象就不是一个单例对象了,在全局可以声明多个该类的实例。(即不是单例了,故单例模式必须将构造函数也声明为私有)
annimal* ani=new annimal;
ani->destory();
3.总结
1. 如果全局只需要一个实例对象,且要实现自动管理资源和释放。构造和析构都要私有,我们只需要调用getinstance 函数就可拿到这个实例。
2.如果在Main中希望通过显示的New来创建对象且可以有多个对象被new,则必须将构造公有,析构私有。且必须实现成员函数destory来delete 对象,不然New出来的对象不会走析构代码。
3.最后还要提供一些静态成员属性和方法来辅助实现。
4.对于自动管理资源的单例对象 有什么好处呢?我们可以在项目中将上述的test.h和test.cpp添加到任何需要该实例的项目中,这样该项目就得到了一个自动管理单例对象的功能,我们只需用就行。且这个实例在main之前构造,main函数之后析构,此时一定时处于单线程的状态,不用关新代码冲突,资源竞争,加锁等问题。
标签:调用,函数,对象,单例,new,annimal From: https://blog.csdn.net/qq_68245364/article/details/139544959