【c++】特殊类的设计

在这里插入图片描述


📄前言

你可听说过只能在堆上创建的类、无法被拷贝的类、甚至是不能继承的类,如果你从未听闻过这样的奇妙的类设计,不妨点进本篇文章,来进入学习设计模式的第一步。

🌻特殊类的设计

当你看到这些要实现的特殊类,可能会感到困惑,为什么需要做出这种看似没有任何意义的类,此时不妨自己动手来实现一下它们,这些看似无用的设计,其实正是通向设计模式的第一步。

无法被继承的类

class NonInherit final	//c++11中,直接使用final即可
{
	NonInherit() {}
};

class NonInherit	//c++98
{
private:
	NonInherit(){}	//私有构造函数即可阻止类被继承
}

只能在堆开辟空间的类

限制类的实例只能在堆上创建,可以通过构造函数私有化,然后通过一个静态的函数来创建类。

class HeapOnly
{
public:
    static HeapOnly* creat()	//静态函数来返回地址
    {
        return new HeapOnly;
    }
private:
    HeapOnly() {};		//设为私有
    HeapOnly(const HeapOnly&) = delete;
};

无法被拷贝的类

防止类的对象被拷贝,可以通过删除拷贝构造函数和赋值运算符来实现。

class Noncopy
{
public:
    Noncopy() {}
    Noncopy &operator=(const Noncopy &) = delete;	//也可设为私有
    Noncopy(const Noncopy &) = delete;
};

只能在栈开辟空间的类

只要在类内把拷贝函数和赋值函数给设为私有或者使用delete(c++11)即可做出在栈开辟空间的类。

class StackOnly
{
public:
    void* operator new(size_t) = delete;
    void operator delete(void*) = delete;
    static StackOnly create()
    {
        return StackOnly();
    }
private:
    StackOnly() {}
};

🌺单例模式

单例模式是一种常用的设计模式,其核心是确保程序中只能一个类只能拥有一个实例,从而实现资源重复利用性,减少性能的损耗。

有了上方特殊类的创建思路,就能更理解饿汉模式与懒汉模式

饿汉模式

饿汉模式,在程序加载类的时候就马上加载实例,这样一来就保证了实例的唯一性。

优点:

  1. 没有线程安全问题,因为在线程开始就被创建。
  2. 实现简单。

缺点:

  1. 可能会造成资源浪费,特别是在还没有用到实例的时候。
  2. 无法控制类的加载顺序,因为在程序加载时就运行,所以会拉慢程序加载速度。
class SingletonEager // 饿汉模式,正如其名一拿到资源就吃掉
{                    // 优点:简单、
public:              // 缺点:可能会造成资源的浪费,没有使用的情况
    static SingletonEager &getInstance()
    {
        return _instance;
    }

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

    static SingletonEager _instance;
};

SingletonEager SingletonEager::_instance;

懒汉模式

懒汉模式指的是在需要用到实例的时候再创建,以此来保证资源不被浪费。

优点:

  1. 减缓内存压力,如果没有用到实例则内存不会被分配。
  2. 加载速度较快。只有在使用时才被创建。

缺点:

  1. 线程安全问题:如果有多个线程同时访问类,需要自己保证资源不会被同时访问,出现二义性问题。
  2. 相比于饿汉模式,实现比较复杂。
class SingletonLazy // 懒汉模式,在需要使用到实例的时候再创建实例,杜绝了资源浪费。
{                   // 优点:没有线程安全问题,杜绝资源浪费
public:             // 缺点:实现较为复杂
    SingletonLazy(const SingletonLazy &) = delete;
    SingletonLazy &operator=(const SingletonLazy &) = delete;

    static SingletonLazy *getInstance()
    {
        if(_instance == nullptr)
        {	// 双重检查来减少锁的使用
            std::lock_guard<std::mutex> lock(_mtx);
            if (_instance == nullptr)
            {
                _instance = new SingletonLazy;
            }
        }
        
        return _instance;
    } // lock_guard 会自动释放 RAII

private:
    SingletonLazy(){};
    static SingletonLazy *_instance;
    static std::mutex _mtx;
};

std::mutex SingletonLazy::_mtx;	//静态成员需要初始化
SingletonLazy *SingletonLazy::_instance = nullptr;

📓总结

设计模式是前人总结出来的开发模板,每一个程序员都应该对它们有所了解,设计模式大致分为三类:创建型、结构型、行为型,本篇介绍了创建型的单例模式,但细算设计模式,一共有23种之多,这些设计模式让我们日后再谈。

单例模式类型饿汉模式懒汉模式
优点:在程序启动时就完成了单例的初始化,保证了线程安全。实现简单。单例实例在需要时才被创建,可以节省资源。对于资源消耗较大的单例,或者在初始化过程中需要依赖参数的情况下非常有用。
缺点:如果程序启动后,单例未被使用,则会造成资源的浪费。初始化单例的过程可能会增加应用程序启动时间。需要在多线程环境下确保线程安全,实现相对复杂,可能会影响性能

📜博客主页:主页
📫我的专栏:C++
📱我的github:github

  • 31
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值