文章目录
- 不能被拷贝的类
- 只能在堆上创建对象的类:
- 方式一
- 方式二
- 设计类只能创建栈对象
- 实现类, 不能被继承
- 单例模式设计
- 饿汉模式
- 懒汉模式
- 线程安全问题
不能被拷贝的类
c++98 只声明(不生成, 编译器默认会生成, 有浅拷贝等的问题), 不实现, 并将其访问设为private
c++11使用=delete来限制
只能在堆上创建对象的类:
只能在堆上创建对象的类:
方式一
delete使用会自动调用析构函数, 所以要销毁这个堆对象, 两种方式:
第二种:
方式二
构造函数私有化, 提供一个函数用于创建对象
这样的方式并不完整, 利用拷贝构造还是能创建栈对象
所以这样的方式还要禁止掉拷贝构造函数才完美
HeapOnly(const HeapOnly& ho) = delete;
设计类只能创建栈对象
私有构造函数, 提供一个接口实现:
但是防不住这样的写法:
这样也不能禁用拷贝构造, 因为在CreateObj中返回局部对象的值要调用拷贝构造,
所以最好的方式是:禁用new 或者是私有化
实现类, 不能被继承
1.构造函数私有化
2.c++11final修饰符
设计模式的概念:被反复使用, 被熟人知晓, 经过分类的, 代码设计经验的总结
(c++是不太关注的, 一般是应用方面比较关注(像Java等语言), 常见的有23种, 这边只细讲单例模式)
迭代器 包装器(适配器)也算设计模式
单例模式设计
思想:对构造函数进行操作
饿汉模式
提前(main函数启动前)准备好,随时getinsert
在类内创建一个该类的对象(此时不允许, 不允许这样的方式来声明), 并且把这个类的对象设为static, 静态的不在对象里面.
这个对象的内存属于静态区, 访问权限属于private, 属于是类内的成员, 此时是属于声明, 定义需要使用类外定义
他的对象获取就需要使用这个方式
同时要禁用拷贝构造和赋值构造:
完整代码及演示
class A
{
public:
static A* GetInsert()
{
return &_inst;
}
void Add(const string& s1, const string& s2)
{
_dict[s1] = s2;
}
void Print()
{
for (auto& e : _dict)
{
cout << e.first << ":" << e.second << endl;
}
}
private:
A() {}
A(const A& a) = delete;
A& operator=(const A& a) = delete;
map<string, string> _dict;
static A _inst;//先声明
};
A A::_inst;//定义
int main()
{
A::GetInsert()->Add("sort", "排序");
A::GetInsert()->Add("right", "向右");
A::GetInsert()->Add("left", "向左");
A::GetInsert()->Print();
return 0;
}
结果演示
优点:
相比懒汉模式, 实现简单, 线程安全
缺点:
可能导致进程启动慢, 创建的单例对象首先会初始化很多
如果两个单例有启动先后顺序, 饿汉模式下无法控制
(导致问题的本质都是对象在main函数之前创建的有关)
懒汉模式
第一次用的时候再去创建(现吃现做)
与上述大致一致, 指向对象的指针初始化为nullptr
在类内构造的接口函数:
其他无异:
class B
{
public:
static B* GetInstance()
{
if (_inst == nullptr)
{
_inst = new B;
}
return _inst;
}
void Add(const string& s1, const string& s2)
{
_dict[s1] = s2;
}
void Print()
{
for (auto& e : _dict)
{
cout << e.first << ":" << e.second << endl;
}
}
private:
B() {}
B(const B& a) = delete;
B& operator=(const B& a) = delete;
map<string, string> _dict;
static B* _inst;//先声明
};
B* B::_inst = nullptr;//定义
int main()
{
B::GetInstance()->Add("sort", "排序");
B::GetInstance()->Add("right", "向右");
B::GetInstance()->Add("left", "向左");
B::GetInstance()->Print();
return 0;
}
结果演示:
懒汉模式下new出来的对象一般不需要进行释放, 进程正常退出会释放资源
但是终有万一: 有的操作下是在析构函数要把数据写入文件,期望是main函数结束自动调用
所以使用 :
1.智能指针
2.内部类(内部类是外部类的友元)
这边演示2 :
线程安全问题
对于懒汉模式, 当有两个线程同时第一个使用, 创建这个对象就有线程安全问题
单例模式最简单的写法:
欢迎随时来进行交流~~~