秒懂C++之特殊类设计

embedded/2024/9/25 17:15:50/

fe594ea5bf754ddbb223a54d8fb1e7bc.gif

目录

 

设计一个类,不能被拷贝

设计一个类,只能在堆上创建对象

设计一个类,只能在栈上创建对象

设计一个类,无法被继承

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

饿汉模式

懒汉模式


设计一个类,不能被拷贝

这个很简单,利用C11新特性中的关键字delete给到拷贝构造与赋值重载即可~

class BanCopy
{//...BanCopy(const BanCopy&) = delete;BanCopy& operator=(const BanCopy&) = delete;//...
};

设计一个类,只能在堆上创建对象

既然是要在堆上创建对象,那么首先要做的就是确保该对象是new出来的而非是由构造函数生成的~

class HeapOnly
{
public://禁止赋值重载HeapOnly& operator=(const HeapOnly&) = delete;//禁止拷贝构造HeapOnly(const HeapOnly&) = delete;
private://构造私有化//无参HeapOnly(){}//有参HeapOnly(int x, int y):_x(x),_y(y){}int _x;int _y;
};int main()
{HeapOnly ho1;HeapOnly* ho2 = new HeapOnly;return 0;
}

不过这样new的时候也无法调用构造了,所以我们再包装一层~

不过还是遇到问题,OBJ是创建对象用的,但调用OBJ得是对象调用,那么我们就不要让它作为成员函数,而是超脱其作用域~

然后再把默认的拷贝函数与赋值重载禁掉,防止在栈上拷贝对象~

class HeapOnly
{
public:template<class... Args>static HeapOnly* CreateObject(Args&&... args){return new HeapOnly(args...);}/*static HeapOnly* CreateObject(){return new HeapOnly;}*///禁止赋值重载HeapOnly& operator=(const HeapOnly&) = delete;//禁止拷贝构造HeapOnly(const HeapOnly&) = delete;
private://构造私有化//无参HeapOnly(){}//有参HeapOnly(int x, int y):_x(x),_y(y){}int _x =1;int _y =2;
};int main()
{/*HeapOnly ho1;HeapOnly* ho2 = new HeapOnly;*/HeapOnly* ho2 = HeapOnly::CreateObject();HeapOnly* ho3 = HeapOnly::CreateObject(3,4);//禁止拷贝//HeapOnly copy(*ho2);return 0;
}

ps:可搭配上前面所学的可变参数模板使用~

设计一个类,只能在栈上创建对象

只能在栈上的话思路和前面差不多,先把构造给私有化,由我们来控制在那开辟对象,再把new给禁止掉,防止在堆上开辟~

class StackOnly
{
public:template<class... Args>static StackOnly CreateObj(Args&&... args){return StackOnly(args...);}// 禁掉operator new可以把下面用new 调用拷贝构造申请对象给禁掉void* operator new(size_t size) = delete;void operator delete(void* p) = delete;
private:StackOnly():_a(0){}
private:int _a;int _b;
};int main()
{StackOnly so1 = StackOnly::CreateObj();StackOnly so2 = StackOnly::CreateObj(3,4);//无法使用StackOnly* ptr3 = new StackOnly(obj);return 0;
}

设计一个类,无法被继承

class A final
{//...
};

直接用C11新特性的关键字final即可~

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

一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个 访问它的全局访问点,该实例被所有程序模块共享

饿汉模式

饿汉:一开始(main之前)就创建出对象。就是说不管你将来用不用,程序启动时就创建一个唯一的实例对象。

想让一些数据,当前程序只有一份,那就可以把这些数据放到这个类里面,再把这个类设计成单例,这个数据就只有一份了

namespace hunger
{class Singleton{public://利用静态成员函数拿到静态成员static Singleton* GetInstance(){return &_sint;}void Print(){cout << _x << endl;cout << _y << endl;}//禁止拷贝构造与赋值重载,防止其他对象生成Singleton(Singleton const&) = delete;Singleton& operator=(Singleton const&) = delete;private://构造函数私有防止构造其他对象Singleton(int x,int y):_x(x), _y(y){}int _x;int _y;// 静态成员对象,不存在对象中,存在静态区,相当于全局的,定义在类中,受类域限制// 这才符合在main之前创建对象static Singleton _sint;};//静态成员声明:成员类型+成员所处內域Singleton Singleton::_sint(1, 1);
}
int main()
{//直接调静态函数拿到对象hunger::Singleton::GetInstance()->Print();
}

ps:之所以拿指针而非对象一个是安全问题,指针销毁方便~但我感觉无论用指针还是引用返回都差不多~

不过饿汉模式有两个问题存在:

  • 如果单例对象数据较多,构造初始化成本较高,那么会影响程序启动的速度。迟迟进不了main函数
  • 多个单例类有初始化启动依赖关系,饿汉无法控制。假设:A和B两个单例,假设要求A先初始化,B再初始化,饿汉无法保证

懒汉模式

懒汉优点:第一次使用实例对象时,创建对象。进程启动无负载。多个单例实例启动顺序自由控
制。
如果单例对象构造十分耗时或者占用很多资源,比如加载插件啊,初始化网络连接啊,读取
文件啊等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,
就会导致程序启动时非常的缓慢。所以这种情况使用懒汉模式( 延迟加载 )更好。
//在饿汉模式基础上进行改造
namespace lazy
{class Singleton{public://利用静态成员函数拿到静态成员static Singleton* GetInstance(){// 第一次调用时,创建单例对象// 线程安全问题,需要加锁if (_psint == nullptr){_psint = new Singleton;}return _psint;}static void DelInstance(){if (_psint){delete _psint;_psint = nullptr;}}void Print(){cout << _x << endl;cout << _y << endl;}//禁止拷贝构造与赋值重载,防止其他对象生成Singleton(Singleton const&) = delete;Singleton& operator=(Singleton const&) = delete;private://构造函数私有防止构造其他对象Singleton(int x =0,int y=0):_x(x), _y(y){}~Singleton(){cout << "~Singleton()" << endl;}int _x;int _y;// 静态成员对象,不存在对象中,存在静态区,相当于全局的,定义在类中,受类域限制static Singleton* _psint;// 内部类class GC{public:~GC(){Singleton::DelInstance();}};// 定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象static GC gc;};Singleton* Singleton::_psint = nullptr;Singleton::GC Singleton::gc;
}
int main()
{//直接调静态函数拿到对象lazy::Singleton::GetInstance()->Print();return 0;
}

在懒汉模式中我们最开始是构建出一个对象指针,只有在第一次被调用的时候才会创建对象,这样可以减少初始化时的开销~由于静态成员变量是指针,那就需要写对应的析构函数及时释放其资源,如果我们不想手动释放也可以学一下构建内部类的方式让其自动调用对指针的析构函数~

如果不想用GC内部类析构对象指针也可以这样写:

namespace lazy
{class Singleton{public://利用静态成员函数拿到静态成员static Singleton* GetInstance(){// 第一次调用时,创建单例对象// 线程安全问题,需要加锁//局部静态对象,在第一次调用该函数时才初始化static Singleton _sint;return &_sint;}static void DelInstance(){if (_psint){delete _psint;_psint = nullptr;}}void Print(){cout << _x << endl;cout << _y << endl;}//禁止拷贝构造与赋值重载,防止其他对象生成Singleton(Singleton const&) = delete;Singleton& operator=(Singleton const&) = delete;private://构造函数私有防止构造其他对象Singleton(int x = 0, int y = 0):_x(x), _y(y){}~Singleton(){cout << "~Singleton()" << endl;}int _x;int _y;// 静态成员对象,不存在对象中,存在静态区,相当于全局的,定义在类中,受类域限制static Singleton* _psint;};Singleton* Singleton::_psint = nullptr;
}int main()
{//直接调静态函数拿到对象lazy::Singleton::GetInstance()->Print();return 0;
}

不用new而是直接创建对象~

总结:在main之前初始化就是饿汉,在main中第一次调用就是懒汉~


http://www.ppmy.cn/embedded/113640.html

相关文章

十.在vue中,发送axios请求应该放在created里还是mounted里?详解

在vue中&#xff0c;发送axios请求应该放在created里还是mounted里&#xff1f;详解 在回答这个问题之前&#xff0c;我们需要知道vue的生命周期钩子顺序&#xff1a;beforecreated&#xff08;组件创建前&#xff0c;dom元素、data都为undefined&#xff09; created&#xf…

通信工程学习:什么是HSS归属用户服务器

HSS&#xff1a;归属用户服务器 HSS&#xff08;归属用户服务器&#xff0c;Home Subscriber Server&#xff09;是IP多媒体子系统&#xff08;IMS&#xff09;中控制层的一个重要组成部分&#xff0c;它扮演着存储和管理用户相关信息的核心角色。以下是关于HSS归属用户服务器的…

Android 开发入门教程-入门基础

1.Android 开发环境 JDK搭建 https://www.cnblogs.com/tianma3798/p/3959626.html 2.Android Sdk 开发环境搭建 AndroidSdk下载地址和环境变量配置 解决Android SDK Manager下载太慢问题(转) 3.Android Avd 虚拟机 4. Android Adb 调试工具 https://www.cnblogs.com/tian…

Java学习线路(2024版)

Java 作为一门成熟、强大且灵活的编程语言&#xff0c;广泛应用于企业级开发、Web开发、移动开发、大数据等领域。随着技术的不断演进&#xff0c;Java 生态系统不断扩展&#xff0c;学习路径也随之更新。如果你想全面掌握 Java&#xff0c;从基础开始到精通&#xff0c;再到最…

如何通过 PhantomJS 模拟用户行为抓取动态网页内容

引言 随着网页技术的不断进步&#xff0c;JavaScript 动态加载内容已成为网站设计的新常态&#xff0c;这对传统的静态网页抓取方法提出了挑战。为了应对这一挑战&#xff0c;PhantomJS 作为一个无头浏览器&#xff0c;能够模拟用户行为并执行 JavaScript&#xff0c;成为了获…

解决:Vue 中 debugger 不生效

目录 1&#xff0c;问题2&#xff0c;解决2.1&#xff0c;修改 webpack 配置2.2&#xff0c;修改浏览器设置 1&#xff0c;问题 在 Vue 项目中&#xff0c;可以使用 debugger 在浏览器中开启调试。但有时却不生效。 2&#xff0c;解决 2.1&#xff0c;修改 webpack 配置 通…

Python Web 应用的安全性防护

Python Web 应用的安全性防护 在构建和维护 Web 应用时&#xff0c;安全性是最关键的方面之一。Web 应用通常面临各种攻击&#xff0c;如 SQL 注入、跨站脚本攻击&#xff08;XSS&#xff09;、跨站请求伪造&#xff08;CSRF&#xff09;等。因此&#xff0c;开发人员必须具备…

数字化转型背景下低代码开发模式变革的研究

摘要 随着数字化转型的不断深入&#xff0c;企业对于快速、高效、灵活的软件开发需求日益增长。低代码开发模式作为一种新兴的软件开发方式&#xff0c;通过减少编码工作量&#xff0c;加速应用交付&#xff0c;正逐渐成为企业数字化转型的重要推动力。本文旨在探讨数字化转型背…