文章目录
不能被复制拷贝的类
思路:使得拷贝构造和赋值重载失效
- C++11可以使用delete,删除对应的拷贝构造和赋值重载
- C++98可以设置成私有的函数
cpp
//不能被复制的类,简单就是禁用拷贝构造和赋值重载
class NonCopy{
public:
NonCopy(){};
// //直接删掉
// NonCopy(const NonCopy& NC)=delete;
// NonCopy operator=(const NonCopy& NC)=delete;
//-------
//下面是C++98做法,就是设置成私有
private:
NonCopy(const NonCopy& NC){};
void operator=(const NonCopy& NC){};
};
只允许在堆上创建对象的类
思路:私有化构造函数,析构函数,拷贝构造函数。设计静态的funtion去提供堆上的对象以及Copy对应的对象
cpp
class OnlyCreatInHeap{
//方法一:私有化其构造函数和析构函数
OnlyCreatInHeap()
{
cout<<"constructor is called\n";
}
~OnlyCreatInHeap()
{
cout<<"destructor is called\n";
}
//就但凭借上述还不足够,还有个可以做到,就是拷贝构造,其可以借用现有对象去创建
OnlyCreatInHeap(const OnlyCreatInHeap & it)
{
//拷贝构在此处
cout<<"Copy constructor is called\n";
}
public:
//这个时候捏,对象大多数时候还没有创建,所以设置成static,防止乱使用this指针,也让外部调用更加便利
static OnlyCreatInHeap* Creat()
{
return new OnlyCreatInHeap;
}
static OnlyCreatInHeap* copy_construct(const OnlyCreatInHeap & it)
{
return new OnlyCreatInHeap(it);
}
void Des()
{
delete this;
}
};
void HeapOnly()
{
// OnlyCreatInHeap a;//无法调用构造函数或者是析构是私有无法创建
OnlyCreatInHeap*p = OnlyCreatInHeap::Creat();
p->Des();
// OnlyCreatInHeap a(*p);//此处会报错了
}
只允许在栈上创建的类
思路一:可以仿照堆得做法,禁用拷贝构造和构造函数,提供静态方法来给出栈的对象。
cpp
1 class StackOnly
2 {
3 public:
4 static StackOnly CreateObject()
5 {
6 return StackOnly();//确保了该类创建对象时不会使用new操作符,从而使得该类只能在栈上创建对象
7 }
8 private:
9 StackOnly(){}//在堆和栈上创建对象都会调用构造函数,为了防止在堆上创建对象,应该将构造函数私有化
10 };
思路二:C++11可以用delete删除对应类里面的new构造,使得外部就不能调用new,这样的问题是该类的定位new也失效了。
cpp
class OnlyCreatInStack
{
public:
OnlyCreatInStack()
{
cout<<"constructor is called\n";
}
public:
//这里返回临时对象就好了,像g++编译器,优化的十分厉害,检测到连续的构造拷贝构造,直接就修改作用域和生命周期以达到目的
static OnlyCreatInStack CreatObj()
{
return OnlyCreatInStack();
}
//如同只在堆上创建一样,拷贝构造也应该想办法不要再new里面实现,但是又不能设为私有之类的操作,因为拷贝构造栈上也要用
//有如下解决
//实现专属的new运算符,这样这个类就new就会搞这个,然后给他delete
void* operator new(size_t size) =delete;
void operator delete(void* p)=delete;
};
// void* OnlyCreatInStack:: operator new(size_t size)
// {
// OnlyCreatInStack* p = (OnlyCreatInStack*)malloc(sizeof(OnlyCreatInStack));
// ::new(p) OnlyCreatInStack;//调用用全局的定位new,也是不行的
// return p;
// }
int Test_CreatOnlyInStack()
{
OnlyCreatInStack a(OnlyCreatInStack::CreatObj());
//OnlyCreatInStack* p = new OnlyCreatInStack;//这样new就行不通了
// OnlyCreatInStack* p = new OnlyCreatInStack(a);//这样new就行不通了
return 0;
}
设计不能继承的类
思路:C++11提供了关键字final,使得类不能被继承。或者也可以纯粹的私有化构造函数
cpp
class NonInherited final
{
};
//这里直接就无通过语法检查
// class Son :public NonInherited
// {
// };
单例:设计一个类,只能由一个对象
设计一个类。使其只能有一个对象
首先根据特点,我们拒绝多次实例化和拷贝
显然是不允许存在拷贝构造,构造函数的,因此私有化
一般来说呢,私有化了拷贝构造,也应该私有化赋值重载
- 饿汉模式:
cpp
//ok,上面的基本要求做完,接下来解决单例的构建问题
//饿汉模式:一开始就创建好,一般来说在main之前,那么我们思考在main函数之前,就创建的一般就是静态区
//:具备全局属性或者静态属性,因此可以在在类的局部里面操作这个问题
//优点:设计简单
//缺点:使得进程启动慢,甚至是卡住启动,如果单例有先后顺序,那么就无法控制
class OnlyOne{
typedef OnlyOne Self;
private:
OnlyOne(const string& s = "",const int& a = 0)
:m()
{
cout<<"OnlyOne begin"<<endl;
}
OnlyOne(const Self& him)
{
};
Self operator=(const Self& him)
{
return *this;
};
~OnlyOne()
{
cout<<"OnlyOne end"<<endl;
}
static OnlyOne _inst;
map<string,int> m;
public:
static Self* GetPtr()
{
return &_inst;
}
void Add(const string& s,int k)
{
m[s] = k;
}
void Print()
{
for(auto it:m)
{
cout<<it.first<<' '<<it.second<<endl;
}
}
};
OnlyOne OnlyOne::_inst ;
int OnlyOne1()
{
OnlyOne* p = OnlyOne::GetPtr();
p->Add("1",2);
p->Add("2",3);
p->Print();
return 0;
}
- 懒汉模式:
cpp
//懒汉模式:使用的时候再实例化
//to do:线程安全问题没有解决 ################################
//new的懒汉都想一般不需要释放,因为程序结束就自动回收资源了
//僵尸进程,提前释放都很少遇见
//如果遇见要求写数据到磁盘,就需要调用析构函数
class OnlyOne2{
private:
OnlyOne2()
{
cout<<"OnlyOne2 begin"<<endl;
}
OnlyOne2(const OnlyOne2& s) = delete;
OnlyOne2 operator=(const OnlyOne2& s) = delete;
~OnlyOne2()
{
cout<<"OnlyOne2 end"<<endl;
}
map<string,int> m;
static OnlyOne2 *_inst;
class gc{
public:
~gc()
{
DelInst();
}
};
static gc _gc;
public:
static OnlyOne2* GetPtr()
{
if(_inst){
return _inst;
}
return _inst = new OnlyOne2;
}
void Add(const string& s,int k)
{
m[s] = k;
}
void Print()
{
for(auto it:m)
{
cout<<it.first<<' '<<it.second<<endl;
}
}
static void DelInst()
{
if(_inst)
{
delete _inst;
_inst = nullptr;
}
}
};
OnlyOne2* OnlyOne2:: _inst =nullptr;
OnlyOne2::gc OnlyOne2::_gc;
int main()
{
OnlyOne2* p = OnlyOne2::GetPtr();
p->Add("1",2);
p->Add("2",3);
p->Print();
return 0;
}