欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > 【C++】特殊类的设计

【C++】特殊类的设计

2024/10/23 23:33:49 来源:https://blog.csdn.net/2201_76024104/article/details/140690030  浏览:    关键词:【C++】特殊类的设计

目录

类的对象只能在堆上创建

类的对象只能在栈上创建

类只能创建一个对象(单例模式)

饿汉

懒汉


本篇博客就是说给一个需求,然后根据需求和类的一些语法规则设计出符合要求的类,比如说我们之前的不能拷贝的类:C++98的做法就是将拷贝构造仅声明且声明在私有,这样编译器不仅不会自动生成,外部也无法调用私有;C++11有关键字delete就可以直接解决,我们再来看一些其他的需求

类的对象只能在堆上创建

对于这种需求我们一般的思路就是封死掉大方向,然后给要求的方向开小门。就是说,我们把构造禁掉,然后单创建一个函数用来专门去堆上开辟空间,这个函数如果是普通成员函数,需要对象来调用,所以我们设置成静态成员函数。至于说拷贝构造和赋值运算符重载都要禁掉,我们就可以这么写

class HeapOnly
{
public:template<class...Args>static HeapOnly* Creatobj(Args&&...args){HeapOnly* tmp = new HeapOnly(forward<Args>(args)...);return tmp;}/*static HeapOnly* Creatobj(int a = 0, const char* str= "aaaaa", vector<double>&& vd = vector<double>()){HeapOnly* tmp = new HeapOnly(a,str,move(vd));return tmp;}*/HeapOnly(const HeapOnly& ho) = delete;//HeapOnly ho1(*pho1);HeapOnly& operator=(const HeapOnly& ho) = delete;//*pho1 = *pho2;void Destroyobj(){delete this;cout << "delete:" << this << endl;}
private:HeapOnly(int a = 0, const char* str = "aaaaa", vector<double>&& vd = vector<double>()):_a(a),_str(str),_vd(vd){}int _a;string _str;vector<double> _vd;
};

或者是我们把析构函数私有化,这样因为调不了析构,所以对象就无法在栈上生成,所以我们就可以去堆上申请(堆上申请的不会自动调用析构),然后创建destroy函数销毁对象

class HeapOnly
{
public:HeapOnly(int a = 0, const char* str = "aaaaa", vector<double>&& vd = vector<double>()):_a(a), _str(str), _vd(vd) {}void Destroyobj(){delete this;cout << "delete:" << this << endl;}
private:~HeapOnly(){cout << "~HeapOnly()" << endl;}int _a;string _str;vector<double> _vd;
};

我们可以这样使用

类的对象只能在栈上创建

这个和只能在堆上创建的大思路是一样的,我们构造私有化,然后单创建一个函数,这个函数就用来返回在栈上的对象,但是返回对象要用到拷贝构造,所以拷贝构造不能禁用。拷贝构造不禁用就可以new对象了,但是new会去调用operator new和(拷贝)构造,所以把operator new给封掉

class StackOnly
{
public:template<class...Args>static StackOnly Creatobj(Args&&...args){return StackOnly(forward<Args>(args)...);}StackOnly(const StackOnly&so):_a(so._a),_str(so._str){}void* operator new(size_t n) = delete;private:StackOnly(int a = 0, const char* str = "aaaa"):_a(a),_str(str){}int _a;string _str;
};

类只能创建一个对象(单例模式)

有的类就要求只创建一个对象,比如内存池,我们每次申请内存都去同一个内存池;比如用来存配置信息的类,我们希望配置信息只有一份,那么这种类的设计方式有饿汉和懒汉两种方式,饿汉就是说在main函数之前这个对象就创建出来了,懒汉就是说等用到的时候才创建,我们下面就来介绍一下这两种方式

饿汉

因为只能创建一个对象,所以要将构造私有化,并且这个对象要创建成静态的,我们再创建一个函数,随时返回这个对象的指针,这样就可以保证要求了

namespace hunger
{class Singleton{public:static Singleton* Getobj(){return &sin;}void print(){cout << _a << endl;for (auto& e : _vs)cout << e << ' ';cout << endl;}Singleton(const Singleton&) = delete;private:Singleton(int a = 0, vector<string>&& vs = {"aaaaaa","bbbbb"}):_a(a),_vs(vs){}int _a;vector<string> _vs;static Singleton sin;};Singleton Singleton::sin(111, { "abc","def" });};

这种创建方式也是有一些问题,如果单例对象数据较多,那么构造初始化这些对象的成本较高,影响程序的启动速度,迟迟进入不了main函数

如果两个单例分别位于两个文件中,它们两个需要有初始化的先后顺序,但是饿汉就无法控制先后顺序,因为很难说哪个文件先,哪个文件后

懒汉

就是说第一次使用的时候再去创建对象,我们也是创建一个静态成员对象,只不过这次是指针,因为通过判断指针是否为空就可以判断是否已经创建了对象

namespace lazy
{class Singleton{public:static Singleton* Getpobj(){if (psin == nullptr){psin = new Singleton;}return psin;}static void destroyobj(){delete psin;}//内部类class GC{public:~GC(){Singleton::destroyobj();}};static GC gc;private:Singleton(int a = 0, vector<string>&& vs = { "aaaaaa","bbbbb" }):_a(a), _vs(vs) {}int _a;vector<string> _vs;static Singleton* psin;};Singleton* Singleton::psin = nullptr;Singleton::GC Singleton::gc;
};

其实还有一种特别简单的方式,就是创建局部的静态对象,那么第一次调用函数就会初始化,后面都不会执行这句代码了

	class Singleton{public:static Singleton* Getpobj(){static Singleton psin;return &psin;}private:Singleton(int a = 0, vector<string>&& vs = { "aaaaaa","bbbbb" }):_a(a), _vs(vs) {}int _a;vector<string> _vs;};

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com