特殊类设计
不能被拷贝的类
C++经典的防拷贝有:unique_ptr
thread
mutex
istream
ostream
要想让一个类不支持拷贝,只要让它的拷贝构造函数和赋值运算符无法调用即可
-
C++98
对拷贝构造函数和赋值运算符只声明,不定义,防止编译器自己生成。并将其访问权限设为私有,防止有人在类外定义。
class CopyBan { //... private: CopyBan(const CopyBan&); CopyBan& operator=(const CopyBan&); //... };
-
C++11
使用 delete
class CopyBan { //... CopyBan(const CopyBan&) = delete; CopyBan& operator=(const CopyBan&) = delete; //... };
只能在堆上创建对象的类
设计思路,将构造函数设为私有,只提供专门在堆上创建对象的接口:
该接口必须设置为静态成员函数,不依赖对象调用。
class HeapOnly
{
public:
static HeapOnly* CreateObj()
{
return new HeapOnly;
}
HeapOnly(const HeapOnly&) = delete;
private:
HeapOnly()
{}
};
为了防止有人在栈上使用拷贝构造,这里可以把拷贝构造删除。
只能在栈上创建对象的类
class StackOnly
{
public:
static StackOnly CreateObj()
{
return StackOnly();
}
StackOnly(const StackOnly&) = delete;
private:
StackOnly()
{}
};
不能被继承的类
-
C++98
将构造函数私有化,派生类不能调用基类中的构造函数,则无法继承
class NonInherit
{
public:
static NonInherit GetInstance()
{
return NonInherit();
}
private:
NonInherit()
{}
};
-
C++11
使用
final
关键字
class A final
{
//...
};
单例模式
一个类只能创建出一个对象,即单例模式
- 饿汉模式
即一开始(main 函数之前)就创建对象,后续只能通过对外提供的接口来获取对象,而不能继续创建。
如下,先把构造函数设为私有,保证无法在类外创建对象。然后在类内创建自己的对象的指针,因为获取对象的函数必须是静态的,而静态成员函数只能使用静态成员变量,所以这个指针也要设置为静态的。静态成员变量类内声明类外定义,由于在声明是类内的,所以它仍属于类内成员,所以可以调用构造函数实例化出对象。
不能忘了把拷贝构造函数删除,防止别人通过拷贝构造创建新的对象。
class Singletion
{
public:
static Singletion* GetInstance()
{
return _spInst;
}
private:
Singletion()
{}
Singletion(const Singletion&) = delete;
static Singletion* _spInst;
};
Singletion* Singletion::_spInst = new Singletion;
- 懒汉模式
即一开始不创建对象,在第一次调用 GetInstance 时创建对象
class Singletion
{
public:
static Singletion* GetInstance()
{
if (_spInst == nullptr)
{
_spInst = new Singletion;
}
return _spInst;
}
private:
Singletion()
{}
Singletion(const Singletion&) = delete;
static Singletion* _spInst;
};
Singletion* Singletion::_spInst = nullptr;
总结:
饿汉模式特点:简单,初始化顺序不确定,如果有依赖关系就会有问题。饿汉对象初始化慢且多个饿汉单例对象会影响程序的启动
懒汉模式特点:复杂一点,初始化顺序可以控制,延迟加载初始化,不影响程序启动。