特殊类设计

文章介绍了如何通过声明但不实现、自定义operatornew和delete、禁止拷贝构造与赋值等方法控制C++类的行为,以及饿汉模式和懒汉模式的单例设计,以及如何避免懒汉模式中的内存泄漏问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

想让默认成员函数不实现功能可以通过以下两个方式:

1.只声明不实现(还会调用,只是没得内容可以执行)

2.在函数尾部添加 = delete 声明(直接向编译器表明没有这个函数了,不会调用)

具体用哪一种是具体情况具体分析,有时候是两个哪一种都行,有时候只能用其中一个。

一、只能在堆上创建

class Creat_heap_only
{
public:
	static Creat_heap_only* Create()
	{
		return new Creat_heap_only;
	}

private:
	Creat_heap_only()
	{}
	Creat_heap_only(const Creat_heap_only& copy)
	{}
	const Creat_heap_only& operator=(Creat_heap_only& copy)
	{}
};

        构造函数拷贝构造函数得删除,以防有人在栈上创建,在栈上只能调用Create_heao_only* p = Create_heao_only::Create();创建新的对象。同时得自己delete p 或者整一个垃圾回收系统,这个系统在懒汉模式会提到。

二、只能在栈上创建

class Creat_stack_only
{
public:
	Creat_stack_only()
	{//...
	}

	void* operator new(size_t n) = delete;
	void operator delete(void* del) = delete;
};

        堆区对象创建和删除都是通过new和delete实现的,因此只需要重载operator函数,只声明不实现即可。

三、创建不能拷贝的对象

class cant_copy
{
	//只声明不实现
	cant_copy(const cant_copy& copy);
	cant_copy& operator=(const cant_copy& copy);
};

        对象拷贝是通过系统调用拷贝构造与赋值运算符重载实现的,因此只需要把这两个函数禁掉,只声明不实现即可。

四、设计一个无法被继承的类

class cant_inherit final
{
	//....
};

        c++11 开始支持final关键字,表明一个类是最终类,无法被继承

五、设计一个类,从始至终只能创建一个对象(单例模式)

        饿汉就是饿了就得吃,所以事先得做好饭;懒汉就是拖延,需要了再去完成,不事先准备。

5.1 饿汉模式

        饿汉模式指的是 这个对象被实际使用之前就得被创建好。就是说不管你将来用不用,程序启动时就创建一个唯一的实例对象。

        所谓成也萧何败也萧何,事先创建好唯一对象即是缺点,也是优点。

        优点:事先创建好唯一对象,后续只管用,不管其他。代码简单。

        缺点:其一,因为先创建好对象,所以启动慢,再万一要是你一直不用,资源也被白白浪费。其二,当多个唯一对象的类创建存在先后关系时,饿汉模式无法适配,原因在于程序启动就创建唯一对象,编译器只管创建对象,可不会管你创建对象时其他组件是否准备齐全。

class single_hungry
{
private:
	single_hungry(){}
	single_hungry(const single_hungry& copy) = delete;
	single_hungry& operator=(const single_hungry& copy) = delete;

	static single_hungry obj;
public:
	static single_hungry* access()
	{
		return &obj;
	}
};
single_hungry single_hungry::obj;

//使用
int main()
{
	single_hungry*use = single_hungry::access();
	return 0;
}

5.2 懒汉模式

        懒汉模式就是:第一次使用实例对象时,创建对象。

        优点:进程启动无负载。多个单例实例启动顺序自由控 制。

        缺点:代码相对复杂

class single_lazy
{
public:
	static single_lazy* access()
	{
		if (obj == nullptr)
		{
			obj = new single_lazy;
		}
		return obj;
	}
private:
	single_lazy() {};
	single_lazy(const single_lazy& copy) = delete;
	single_lazy& operator=(const single_lazy& copy) = delete;

	static single_lazy* obj;
};
single_lazy* single_lazy::obj = nullptr;

int main()
{
	single_lazy* use = single_lazy::access();
	delete use;
	return 0;
}

       饿汉模式是直接创建了一个对象,而懒汉模式是创建了一个指针。懒汉模式第一次使用,即第一次调用access函数时,给这个指针分配空间(new)。因为懒汉模式是在堆区分配的空间,因此需要手动释放,而饿汉创建的对象是在静态区,因此随着程序结束,会自动释放。所以说,懒汉模式得自己释放空间,这就很麻烦,万一有的人忘了,这不就极易造成内存泄漏。那有没有一种办法,让程序自动帮我们释放?

        很简单,创建一个与懒汉单例对象(堆区)同样生命周期的实例对象-回收对象(静态区),当程序结束生命周期结束时,回收对象析构函数设定成delete 懒汉单例对象指针即可。

class single_lazy
{
public:
	static single_lazy* access()
	{
		if (obj == nullptr)
		{
			obj = new single_lazy;
		}
		return obj;
	}



private:
	single_lazy() {};
	single_lazy(const single_lazy& copy) = delete;
	single_lazy& operator=(const single_lazy& copy) = delete;

	static single_lazy* obj;

	struct recycle
	{
		~recycle()
		{
			delete obj;
		}
	};
	static recycle rec;
};
single_lazy* single_lazy::obj = nullptr;
single_lazy::recycle single_lazy::rec;//程序结束 调rec的析构函数,就把obj指针指向的内容释放了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值