C++项目实战——基于多设计模式下的同步异步日志系统-③-前置知识补充-设计模式

news2024/11/24 13:05:42

文章目录

  • 专栏导读
  • 六大原则
  • 单例模式
    • 饿汉模式
    • 懒汉模式
  • 工厂模式
    • 简单工厂模式
    • 工厂方法模式
    • 抽象工厂模式
  • 建造者模式
  • 代理模式

专栏导读

🌸作者简介:花想云 ,在读本科生一枚,C/C++领域新星创作者,新星计划导师,阿里云专家博主,CSDN内容合伙人…致力于 C/C++、Linux 学习。

🌸专栏简介:本文收录于 C++项目——基于多设计模式下的同步与异步日志系统

🌸相关专栏推荐:C语言初阶系列C语言进阶系列C++系列数据结构与算法Linux

在这里插入图片描述
设计模式是一种在软件设计中常见的可重用解决方案的方法。它们是经过反复验证和证明的最佳实践,可以帮助软件开发人员解决特定问题或应对常见的设计挑战。设计模式提供了一种通用的框架,有助于构建高质量、易于维护和可扩展的软件系统

六大原则

  • 单一职责原则

    • 类的职责应该单一,一个方法只做一件事。职责划分清晰明了,每次改动到最小的方法或类;
    • 使用建议:两个完全不一样的功能不应该放在一个类中,一个类应该是一组相关性很高的函数、数据的封装;
    • 用例:网络聊天:网络通信&聊天,应该分割为网络通信类或聊天类;
  • 开闭原则

    • 对扩展开放,对修改封闭
    • 使用建议:对软件实体的改动,最好使用拓展而非修改的方式;
    • 用例:超市卖货:商品价格时长需要改动,但不是修改原来商品的价格而是新增促销价格;
  • 里氏替换原则

    • 通俗点讲,就是只要父类能出现的地方,子类就可以出现,而且替换为子类也不会出现任何错误或异常
    • 在继承类时,务必重写父类中所有的方法,尤其需要注意父类的protected方法,子类尽量不要暴露自己的public方法供外界调用;
    • 使用建议:子类必须完全实现父类的方法,孩子可以有自己的个性。覆盖或实现父类的方法时,输入参数可以被放大,输出可以缩小;
    • 用例:跑步运动员类会跑步,子类长跑运动员会跑步且擅长长跑,子类短跑运动员会跑步且擅长短跑;
  • 依赖倒置原则

    • 高层模块不应该依赖低层模块,两者都应该依赖其抽象。不可分割的原子逻辑就是低层模式,原子逻辑组装成的就是高层模块;
    • 模块间依赖通过抽象(接口)发生,具体类之间不之间依赖
    • 使用建议:每个类都尽量有抽象类,任何类都不应该从具体类派生。尽量不要重写基类的方法。结合里氏替换原则使用。
    • 用例:奔驰车司机类只能开奔驰,司机类给什么车就开什么车,开车的人:司机——依赖于抽象;
  • 迪米特法则

    • 尽量减少对象之间的交互,从而减少类之间的耦合。一个对象应该对其他对象有最少的了解。对类的低耦合提出了明确的要求:
      • 只和直接的朋友交流,朋友之间也是有距离的。自己的就是自己的(如果一个方法放在本类中,既不增加类间关系,也不产生负面影响,那就放置在本类中;
    • 用例:老师让班长点名,老师给班长一个名单,班长点完名勾选,返回结果,而不是班长点名,老师勾选;
  • 接口隔离原则

    • 客户端不应该依赖他不需要的接口,类间的依赖关系应该建立在最小的接口上
    • 使用建议:接口设计尽量精简单一,但是不要对外暴露没有实际意义的接口;
    • 用例:修改密码:不应该提供修改用户信息接口,而就是单一的最小修改密码的接口;

从整体上来了解六大原则,可以简要的概括为一句话:用抽象构建框架,用实现拓展细节。具体到每一条设计原则,则对应一条注意事项:

  • 单一职责原则告诉我们实现类要职责单一
  • 里氏替换原则告诉我们不要破坏继承体系
  • 依赖倒置原则告诉我们要面向接口编程
  • 接口隔离原则告诉我们在设计接口时要降低耦合
  • 开闭原则是总纲,告诉我们要对拓展开放,对修改关闭

单例模式

  • 一个类只能创建⼀个对象,即单例模式,该设计模式可以保证系统中该类只有一个实例,并提供⼀个访问它的全局访问点,该实例被所有程序模块共享。
  • 比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由⼀个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。

单例模式有两种实现模式:饿汉模式和懒汉模式。

饿汉模式

  • 程序启动时就会创建一个唯一的实例对象。因为单例对象已经确定,所以比较适用于多线程环境中,多线程获取单例对象不需要加锁可以有效的避免资源竞争,提高性能
#include <iostream>
#include <string>

// 饿汉模式
class Singleton
{
public:
    Singleton(const Singleton &) = delete;
    Singleton& operator=(const Singleton&) = delete;
    static Singleton& getInstance()
    {
        return _eton;
    }
    std::string &getData()
    {
        return _data;
    }
private:
    Singleton() :_data("Singleton") 
    {
        std::cout << "获取单例对象" <<std::endl;
    }
    ~Singleton() {}
private:
    static Singleton _eton;
    std::string _data;
};

Singleton Singleton::_eton;

int main()
{
    std::cout << Singleton::getInstance().getData() << std::endl;
    return 0;
}

懒汉模式

  • 第一次要使用单例对象的时候创建实例对象。如果单例对象构造特别耗时或者耗费资源(加载插件、加载网络资源等),可以选择懒汉模式,在第一次使用的时候才创建对象。
    • C++11后,静态变量能够满足在线程安全的前提下唯一的被构造和析构
// 懒汉模式
class Singleton
{
public:
    Singleton(const Singleton &) = delete;
    Singleton &operator=(const Singleton &) = delete;
    static Singleton &getInstance()
    {
        static Singleton _eton; 
        return _eton;
    }
    std::string &getData()
    {
        return _data;
    }
private:
    Singleton() : _data("Singleton")
    {
        std::cout << "单例对象构造" << std::endl;
    }
    ~Singleton() {}
private:
    static Singleton _eton;
    std::string _data;
};

工厂模式

  • 工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们创建对象时不会对上层暴露创建逻辑,而是通过使用一个共同结构来指向新创建的对象,以此实现创建与使用的分离

工厂模式可以分为:

  • 简单工厂模式;
  • 工厂方法模式;
  • 抽象工厂模式;

简单工厂模式

  • 简单工厂模式实现由一个工厂对象通过类型来决定创建出来指定产品类的实例
  • 假设有个工厂能生产出水果,当客户生产水果的时候明确告诉工厂生产哪类水果,工厂需要接收用户提供的类别信息,当新增产品的时候,工厂内部去添加新产品的生产方式。
/*
    简单工厂模式:通过参数控制可以生产任何商品
        优点:简单粗暴、直观易懂。使用一个工厂生产同一等级结构下的任意商品
        缺点:
            1.所有东西生产在一起,产品太多会导致代码量庞大;
            2.开闭原则遵守不是太好,要新增产品就必须修改工厂方法。
*/
#include <iostream>

class Fruit
{
public:
    Fruit() {}
    virtual void name() = 0;
};

class Apple : public Fruit
{
public:
    Apple() {}
    virtual void name()
    {
        std::cout << "苹果" << std::endl;
    }
};

class Banana : public Fruit
{
public:
    Banana() {}
    virtual void name()
    {
        std::cout << "香蕉" << std::endl;
    }
};

class FruitFactory
{
public:
    static std::shared_ptr<Fruit> create(const std::string &name)
    {
        if (name == "苹果")
            return std::make_shared<Apple>();
        else if (name == "香蕉")
            return std::make_shared<Banana>();
        return std::shared_ptr<Fruit>();
    }
};

int main()
{
    std::shared_ptr<Fruit> ff = FruitFactory::create("苹果");
    ff->name();

    ff = FruitFactory::create("香蕉");
    ff->name();
    return 0;
}

工厂方法模式

  • 在简单工厂模式下新增多个工厂,多个产品,每个产品对应一个工厂
  • 假设现在有A、B两种产品,则开两个工厂,工厂A负责生产产品A,工厂B负责生产产品B,用户只知道产品的工厂名,而不知道具体的产品信息,工厂不需要再接收客户的产品类别,而只负责生产产品。
/* 
    工厂方法模式:定义一个创建对象的接口,但是由子类来决定创建哪种对象,使用多个工厂分别生产指定的固定产品
        优点:
            1.减轻了工厂类的负担,将某产品的生产交给指定的工厂来进行;
            2.开闭原则遵循较好,添加新产品只需要新增产品的工厂即可,不需要修改原先的工厂类。
        缺点:
            对于某种可以形成一组产品族的情况处理较为复杂,需要创建大量的工厂类。
    
*/
#include <iostream>
#include <string>
#include <memory>

class Fruit
{
public:
    Fruit() {}
    virtual void name() = 0;
};

class Apple : public Fruit
{
public:
    Apple() {}
    virtual void name()
    {
        std::cout << "苹果" << std::endl;
    }
private:
    std::string _color;
};

class Banana : public Fruit
{
public:
    Banana() {}
    virtual void name()
    {
        std::cout << "香蕉" << std::endl;
    }
};

class FruitFactory
{
public:
    virtual std::shared_ptr<Fruit> create() = 0;
};

class AppleFactory : public FruitFactory
{
public:
    virtual std::shared_ptr<Fruit> create()
    {
        return std::make_shared<Apple>();
    }
};

class BananaFactory : public FruitFactory
{
public:
    virtual std::shared_ptr<Fruit> create()
    {
        return std::make_shared<Banana>();
    }
};

int main()
{
    std::shared_ptr<FruitFactory> factory(new AppleFactory());
    std::shared_ptr<Fruit> fruit = factory->create();
    fruit->name();

    factory.reset(new BananaFactory());
    fruit = factory->create();
    fruit->name();

    return 0;
}

抽象工厂模式

  • 工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂职责太重的问题,但由于工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,势必会增加系统的开销。此时,我们可以考虑将一些相关的产品组成一个产品族(位于不同产品等级结构中功能相关联的产品组成的家族),由同一个工厂来统一生产,这就是抽象工厂模式的基本思想。
/*
    抽象工厂:围绕一个超级工厂去创建其他工厂。每个生成的工厂按照工厂模式提供对象。
        思想:将工厂抽象成两层,抽象工厂 & 具体工厂子类,在工厂子类中生产不同类型的子产品
*/
#include <iostream>
#include <string>
#include <memory>

class Fruit
{
public:
    Fruit() {}
    virtual void name() = 0;
};

class Apple : public Fruit
{
public:
    Apple() {}
    void name() override
    {
        std::cout << "苹果" << std::endl;
    }

private:
    std::string _color;
};

class Banana : public Fruit
{
public:
    Banana() {}
    void name() override
    {
        std::cout << "香蕉" << std::endl;
    }
};

class Animal
{
public:
    virtual void voice() = 0;
};

class Cat : public Animal
{
public:
    void voice() override
    {
        std::cout << "喵喵喵" << std::endl;
    }
};

class Dog : public Animal
{
public:
    void voice() override
    {
        std::cout << "汪汪汪" << std::endl;
    }
};

class Factory
{
public:
    virtual std::shared_ptr<Fruit> getFruit(const std::string &name) = 0;
    virtual std::shared_ptr<Animal> getAnimal(const std::string &name) = 0;
};

class FruitFactory : public Factory
{
public:
    std::shared_ptr<Animal> getAnimal(const std::string &name) override
    {
        return std::shared_ptr<Animal>();
    }

    std::shared_ptr<Fruit> getFruit(const std::string &name) override
    {
        if (name == "苹果")
            return std::make_shared<Apple>();
        else if (name == "香蕉")
            return std::make_shared<Banana>();
        return std::shared_ptr<Fruit>();
    }
};

class AnimalFactory : public Factory
{
public:
    std::shared_ptr<Fruit> getFruit(const std::string &name) override
    {
        return std::shared_ptr<Fruit>();
    }

    std::shared_ptr<Animal> getAnimal(const std::string &name) override
    {
        if (name == "小猫")
            return std::make_shared<Cat>();
        else if (name == "小狗")
            return std::make_shared<Dog>();
        return std::shared_ptr<Animal>();
    }
};

class FactoryProducer
{
public:
    static std::shared_ptr<Factory> getFactory(const std::string &name)
    {
        if (name == "水果")
            return std::make_shared<FruitFactory>();
        else if(name == "动物")
            return std::make_shared<AnimalFactory>();
    }
};

int main()
{
    std::shared_ptr<Factory> fruit_factory = FactoryProducer::getFactory("水果");
    std::shared_ptr<Fruit> fruit = fruit_factory->getFruit("苹果");
    fruit->name();
    fruit = fruit_factory->getFruit("香蕉");
    fruit->name();

    std::shared_ptr<Factory> animal_factory = FactoryProducer::getFactory("动物");
    std::shared_ptr<Animal> animal = animal_factory->getAnimal("小猫");
    animal->voice();
    animal = animal_factory->getAnimal("小狗");
    animal->voice();
    
    return 0;
}

建造者模式

  • 建造者模式是一种创建型设计模式使用多个简单的对象一步一步构建出一个复杂的对象,能够将一个复杂的对象的构建与它的表示分离,提供一种创建对象的最佳方式。主要用于解决对象的构建过于复杂的问题。

建造者模式主要基于4个核心类实现:

  • 抽象产品类;
  • 具体产品类:一个具体的产品对象类;
  • 抽象pubic类:创建一个产品对象所需的各个部件的抽象接口;
  • 具体产品的Builder类:实现抽象接口,构建各个部件;
  • 指挥者Director类:统一组建过程,提供给调用者使用,通过指挥者来构建产品;
#include <iostream>
#include <memory>

/* 抽象电脑类 */
#include <iostream>
#include <memory>

class Computer
{
public:
    using ptr = std::shared_ptr<Computer>;

    Computer() {};

    void setBoard(const std::string &board) { _board = board ;}
    void setDisplay(const std::string &display) {_display = display;}
    virtual void setOs() = 0;
    std::string show()
    {
        std::string computer = "Computer:[\n";
        computer += "\tboard: " + _board + "\n";
        computer += "\tdisplay: " + _display + "\n";
        computer += "\tos: " + _os + "\n";
        computer += "]\n";
        return computer;
    }
protected:
    std::string _board;
    std::string _display;
    std::string _os;
};

/* 具体产品类 */
class MacBook : public Computer
{
public:
    using ptr = std::shared_ptr<MacBook>;
    MacBook() {}
    virtual void setOs() 
    {
        _os = "Mac Os X12";
    }
};

/* 抽象建造者类:包含创建一个产品对象各个部件的抽象接口 */
class Builder
{
public:
    using ptr = std::shared_ptr<Builder>;
    virtual void buildBoard(const std::string &board) = 0;
    virtual void buildDisplay(const std::string &display) = 0;
    virtual void buildOS() = 0;
    virtual Computer::ptr build() = 0;
};

/* 具体产品的具体建造者类:实现抽象接口,构建和组装各个部件 */
class MacBookBuilder : public Builder
{
public:
    using ptr = std::shared_ptr<MacBookBuilder>;
    MacBookBuilder() : _computer(new MacBook()) {}
    virtual void buildBoard(const std::string &board) 
    {
        _computer->setBoard(board);
    }

    virtual void buildDisplay(const std::string &display)
    {
        _computer->setDisplay(display);
    }

    virtual void buildOS()
    {
        _computer->setOs();
    }

    virtual Computer::ptr build()
    {
        return _computer;
    }
private:
    Computer::ptr _computer;
};

/* 指挥者类:提供给调用者使用,通过指挥者来构造复杂的产品 */
class Director
{
public:
    Director(Builder* builder) : _builder(builder) {}
    void construct(const std::string &board, const std::string &display)
    {
        _builder->buildBoard(board);
        _builder->buildDisplay(display);
        _builder->buildOS();
    }
private:
    Builder::ptr _builder;
};

int main()
{
    Builder* builder = new MacBookBuilder();
    std::unique_ptr<Director> pd(new Director(builder));
    pd->construct("华为主板", "VOC显示器");
    Computer::ptr computer = builder->build();
    std::cout << computer->show() ;

    return 0;
}

代理模式

  • 代理模式指代理控制对其他对象的访问,也就是代理对象控制对原对象的引用。在某些情况下,一个对象不能或不适合直接被引用访问,而代理对象可以在客户端与目标对象之间起到中介作用

  • 代理模式的结构包括一个真正的你要访问的对象(目标类)、一个是代理对象。目标对象与代理对象实现同一个接口,先访问代理类,再通过代理类来访问目标对象。代理模式分为静态代理、动态代理:

    • 静态代理指的是:在编译时就已经确定好了代理类和被代理类的关系。也就是说,在编译时就已经确定了代理类要代理的是哪一个类。

    • 动态代理指的是:在运行时才动态生产代理类,并将其与被代理类绑定。这意味着在运行时才能确定代理类要代理的是哪一个类。

以租房为例,房东将房子租出去,但是房子要租出去,需要发布招租启示,带人看房,负责维修,这些操作中有些操作并非房东能完成,因此房东为了图省事,将房子委托给中介进行租赁。

#include <iostream>
#include <string>
/*房东要把⼀个房⼦通过中介租出去理解代理模式*/

/* 租房类 */
class RentHouse
{
public:
    virtual void rentHouse() = 0;
};

/* 房东类 */
class Landlord : public RentHouse
{
    public:
        void rentHouse() 
        {
            std::cout << "将房子租出去\n" << std::endl;
        }
};

/* 中介类 */
class Intermedirary : public RentHouse
{
    public:
        void rentHouse()
        {
            std::cout << "发布告示" << std::endl;
            std::cout << "带人看房" << std::endl;
            _landlord.rentHouse();
            std::cout << "负责租后维修" << std::endl;

        }
    private:
        Landlord _landlord;
};

int main()
{
    Intermedirary intermedirary;
    intermedirary.rentHouse();

    return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/993943.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LP(六十九)智能文档助手升级

本文在笔者之前研发的大模型智能文档问答项目中&#xff0c;开发更进一步&#xff0c;支持多种类型文档和URL链接&#xff0c;支持多种大模型接入&#xff0c;且使用更方便、高效。 项目介绍 在文章NLP&#xff08;六十一&#xff09;使用Baichuan-13B-Chat模型构建智能文档中…

CodeJock Active-X / COM v22.1.0 Crack

CodeJock Active-X / COM v22.1.0--这个支持 Unicode 啦&#xff0c; Unicode Unicode 创建专业应用程序&#xff0c;其中包含一整套高度可定制的用户界面组件&#xff0c;包括 Visual Studio 风格的对接窗格和 Office 风格的功能区、工具栏和菜单&#xff0c;为您的应用程序…

电商邮件营销攻略:教你如何有效运营邮件营销策略!

作为一种领先的营销渠道&#xff0c;电子邮件营销已被电子商务公司作为推动客户参与度、促进销售和提高ROI的不可或缺的方式。在这篇文章中&#xff0c;我们将深入探讨电子商务公司为什么要做EDM邮件营销&#xff1f;以及电商公司怎么做邮件营销&#xff1f; 一、电子商务公司…

系统架构设计师(第二版)学习笔记----多媒体技术

【原文链接】系统架构设计师&#xff08;第二版&#xff09;学习笔记----多媒体技术 文章目录 一、多媒体概述1.1 媒体的分类1.2 多媒体的特征1.3 多媒体系统的基本组成 二、多媒体系统的关键技术2.1 多媒体系统的关键技术2.2 视频技术的内容2.3 音频技术的内容2.4 数据压缩算法…

时序分解 | MATLAB实现基于SSA奇异谱分析的信号分解分量可视化

时序分解 | MATLAB实现基于LMD局部均值分解的信号分解分量可视化 目录 时序分解 | MATLAB实现基于LMD局部均值分解的信号分解分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 奇异谱分解奇异谱分析SSA 可直接替换txt数据运行 Matlab 1.包含3D分解效果图 频谱图等…

多路转接之PollEpoll

文章目录 Pollpoll函数接口poll的优缺点poll示例Util.hpp(所用到的函数方法)Server.hppServer.cclog.hpp(日志) Epollepoll的相关系统调用epoll_createepoll_ctlepoll_wait epoll工作原理epoll的优点epoll工作方式对比LT和ETepoll服务器(LT模式)示例Util.hpp(需要调用的函数)Se…

DeepinV20/Ubuntu安装postgresql方法

首先&#xff0c;建议看一下官方的安装文档PostgreSQL: Linux downloads (Ubuntu) PostgreSQL Apt Repository 简单的说&#xff0c;就是Ubuntu下的Apt仓库&#xff0c;可以用来安装任何支持版本的PgSQL。 If the version included in your version of Ubuntu is not the one…

一笑的大型连续剧之第二集

开场白 各位小伙伴们大家晚上好&#xff0c;今天来和大家一起更新一下我的开发之旅的第二集。上周时间也已经匆匆过去了。今天也是周六晚上了&#xff0c;这个周末很充实但是又很空虚。 本周小结 本周完成了我开发旅途中的第一个模块&#xff0c;关于绩效面谈的一个模块的一…

树莓派入门

目录 前言系统烧录使用官方烧录工具选择操作系统选择存储卡配置 Win32DiskImager 有屏幕树莓派开机树莓派关机无屏幕树莓派开机获取树莓派IP地址通过路由器获取共享网络方式获取给树莓派配置静态IP地址查找默认网关分盘给树莓派的IP地址修改树莓派DHCP配置文件 ssh登录 让树莓派…

排序(408)

一、插入排序&#xff08;直接、折半、希尔&#xff09; 【2009统考】若数据元素序列{11,12,13,7,8,9,23,4,5}是采用下列排序方法之一得到的第二趟排序后的结果&#xff0c;则该排序算法只能是&#xff08;B&#xff09; A、冒泡排序 B、插入排序 C、选择排序 …

freemarker模板引擎详解以及使用方法

哈喽&#xff01;大家好&#xff0c;我是旷世奇才李先生 文章持续更新&#xff0c;可以微信搜索【小奇JAVA面试】第一时间阅读&#xff0c;回复【资料】更有我为大家准备的福利哟&#xff0c;回复【项目】获取我为大家准备的项目 文章目录 一、freemarker 介绍1、简介 二、free…

Java 基于 SpringBoot 的酒店管理系统,附源码和数据库

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,Csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 一、前言介绍二、系统结构三、系统详细实现3.1用户信息管理3.2会员信息管理3.3客房信息管理3.4收藏…

浅析linux异步io框架 io_uring

前言 Linux内核5.1支持了新的异步IO框架iouring&#xff0c;由Block IO大神也即Fio作者Jens Axboe开发&#xff0c;意在提供一套公用的网络和磁盘异步IO&#xff0c;不过io_uring目前在磁盘方面要比网络方面更加成熟。 目录 背景简介 io_uring 系统API liburing 高级特性…

SpringBoot实例类-@Data

1.配置pom.xml 说明&#xff1a;添加lombok依赖 <!-- lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency> 2.刷新maven 说明&#xff1a;一般修改xml文件就需要刷…

数据库相关基础知识

第一章 概念 1、数据&#xff1a;描述事物的符号记录称为数据。特点&#xff1a;数据和关于数据的解释不可分。 2、数据库&#xff1a;长期存储在计算机内、有组织、可共享的大量的数据的集合。数据库中的数据按照一定的数据模型组织、描述和存储&#xff0c;具有较小的冗余度、…

Linux —— 信号阻塞

目录 一&#xff0c;信号内核表示 sigset_t sigprocmask sigpending 二&#xff0c;捕捉信号 sigaction 三&#xff0c;可重入函数 四&#xff0c;volatile 五&#xff0c;SIGCHLD 信号常见概念 实际执行信号的处理动作&#xff0c;称为信号递达Delivery&#xff1b;信…

广东智科与涂鸦智能达成合作,引领热泵市场智能转型新风向

全球能源危机正推动热泵市场的增长&#xff0c;据国际能源署报道&#xff0c;2022年全球热泵的销售额增长达11%&#xff0c;欧洲的销售额增长更是达到了40%。中国作为热泵市场的最大出口国&#xff0c;全球热泵市场需求的激增对于中国企业而言无疑是一剂“振奋剂”。 广东智科电…

QT/QTCreator开发/使用技巧

调试模式完整的展示过长的字符串 如图&#xff0c;当字符串过长时在调试模式下&#xff0c;无法非常清晰的看到全部的字符串&#xff0c;此时可以通过 右键菜单→ change value display format→spearate Window。此时字符串将单独显示在一个独立的窗口里。如果你想回到原状勾选…

关于“找不到mfc140u.dll,无法继续执行代码”问题的分析处理方法

我想和大家分享一个在编程过程中经常会遇到的问题——找不到mfc140u.dll,无法继续执行代码。找不到 mfc140u.dll&#xff0c;这个问题可能会让我们感到困扰。mfc140u.dll 是 Microsoft Foundation Classes&#xff08;MFC&#xff09;库的一部分&#xff0c;它是一个 Windows 系…

MySQL——读写分离

简介 读写分离&#xff0c;基本的原理是让主数据库处理事务性增、改、删操作&#xff08;INSERT、UPDATE、DELETE&#xff09;&#xff0c;而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。一般来说都是通过 主从复制&#xff…