目录
1一个类,不能被拷贝
我们只需要禁止调用拷贝构造函数和赋值运算符重载就行了。
C++98:
class A
{
private:
A(const A&);
A& operatot = (const A &);
};
①.将拷贝构造函数和赋值运算符重载私有化,类外面调不了。
②.只声明不定义,反正用不到,不定义更便捷,而且防止类内调用。
C++11:
class B
{
B(const B&) = delete;
B& operatot = (const B&) = delete;
};
①=delete 如果跟在默认成员函数后面,表示让编译器删除掉该默认成员函数。
2.一个类,只能在堆上创建对象
class C
{
public:
static C* newC()
{
return new C;
}
C(const C&) = delete;
private:
C();
};
①构造函数私有化,防止类外面的调用,以免在栈上生成对象。
②将成员函数设为静态,在该静态成员函数中,在堆上创建对象。设成静态的原因是,要通过对象去调用成员函数,但是此时类外面禁止调用构造函数,就没有对象来调用该函数去生成对象,这是一个先有鸡还是先有蛋的问题。所以使用static,静态成员函数不用对象来调。而且,构造函数不用this指针来调用。
③防止拷贝构造创建栈上的对象。
3.一个类,只能在栈上创建对象
class D
{
public:
static D stackD()
{
return D();
}
D(const D&) = delete;
private:
D();
};
Dd=D::stackD();
①同上,但有一点,调用静态成员函数返回时必要拷贝构造建立一个临时对象,然后再拷贝构造给对象d,但是有些编译器会优化,直接将几步,合并为一步构造。
class E
{
static E stackE()
{
return E();
}
public:
void* operator new(size_t sz) = delete;
};
我们写一个专属的operator new,将它禁掉,在类外面new的时候,new不会去调用全局的operator new。我前面的博客写过,new在使用时,在底层调用operator new函数,再调用类的构造函数,所以这方法可行,但是有一个缺点。防不住:
E e = E::stackE();
static E copy(e);
所以还要禁掉拷贝构造函数,还是第一个方法简便。
4.一个类,不能被继承
C++98:
class F
{
public:
static F GetInstance()
{
return F();
}
private:
F();
};
基类的构造函数继承到子类,但是基类的构造函数是私有,对子类来说是不可见的,调不到基类的构造函数。则无法继承。
C++11:
class G final
{
};
final关键字,final修饰类,表示该类不能被继承。
5.单例模式:饿汉模式
一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
饿汉模式:程序启动时就创建一个唯一的实例对象。
class SingleH
{
public:
static SingleH* GetMember()
{
return sh;
}
private:
SingleH()
{
}
SingleH(const SingleH&) = delete;
SingleH& operator=( const SingleH&) = delete;
static SingleH* sh;
};
SingleH* SingleH::sh = new SingleH;
①拷贝构造私有,类外面调不到,初始化不了,而static SingleH* sh,写到类里面,可以调用构造函数。
②防止拷贝构造。拷贝和赋值全部禁止。
6.单例模式:懒汉模式
懒汉模式:第一次使用实例对象时,创建对象。
class SingleI
{
public:
static SingleI* GetMember()
{
if (si == nullptr)
{
si = new SingleI;
}
return si;
}
//内嵌垃圾回收类
class CGarbo {
public:
~CGarbo() {
if (SingleI::si)
delete SingleI::si;
}
};
//程序结束时,会调用该类的析构函数从而释放单例对象
static CGarbo Garbo;
private:
SingleI()
{
}
SingleI(const SingleI&) = delete;
SingleI& operator=(const SingleI&) = delete;
static SingleI* si;
};
SingleI* SingleI::si = nullptr;
SingleI::CGarbo SingleI:: Garbo;
总结:
饿汉模式:
初始化顺序不确定,饿汉初始化慢,且多个饿汉单例对象会影响程序启动。
懒汉模式:
在第一次调用时初始化,可以控制初始化顺序,延迟初始化,不影响程序启动。