特殊的类设计 and 单例模式

目录

1一个类,不能被拷贝

2.一个类,只能在堆上创建对象

3.一个类,只能在栈上创建对象

4.一个类,不能被继承

5.单例模式:饿汉模式

6.单例模式:懒汉模式

总结:


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;

总结:

饿汉模式:

初始化顺序不确定,饿汉初始化慢,且多个饿汉单例对象会影响程序启动。

懒汉模式:

在第一次调用时初始化,可以控制初始化顺序,延迟初始化,不影响程序启动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值