当前位置: 首页 > news >正文

事件传播机制 与 责任链模式

1、基本概念
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,将请求沿着处理链传递,直到有一个对象能够处理为止。

2、实现的模块有:

Handler(处理者):定义一个处理请求的接口。
ConcreteHandler(具体处理者):实现了处理者接口,判断自己是否能够处理请求,如果不能将请求传递给下一个处理者。
Request(请求):封装了请求的信息,通常作为处理者方法的参数传递。
3、使用场景
当需要将请求的发送者和接收者进行解耦时。
当有多个对象可以处理同一请求,但不确定哪个对象应该处理时。
当需要动态指定处理请求的顺序时。

4、责任链模式的C++实现

#include <iostream>  
#include <memory>  
#include <string>  // 抽象处理器类  
class Handler {  
public:  virtual ~Handler() {}  // 处理请求的方法  virtual void HandleRequest(const std::string& request) {  if (successor_) {  successor_->HandleRequest(request);  }  }  // 设置后继处理器  void setSuccessor(std::shared_ptr<Handler> successor) {  successor_ = successor;  }  protected:  std::shared_ptr<Handler> successor_;  
};  // 具体处理器类A  
class ConcreteHandlerA : public Handler {  
public:  void HandleRequest(const std::string& request) override {  if (request == "A") {  std::cout << "ConcreteHandlerA handles the request: " << request << std::endl;  } else {  Handler::HandleRequest(request);  }  }  
};  // 具体处理器类B  
class ConcreteHandlerB : public Handler {  
public:  void HandleRequest(const std::string& request) override {  if (request == "B") {  std::cout << "ConcreteHandlerB handles the request: " << request << std::endl;  } else {  Handler::HandleRequest(request);  }  }  
};  // 具体处理器类C  
class ConcreteHandlerC : public Handler {  
public:  void HandleRequest(const std::string& request) override {  if (request == "C") {  std::cout << "ConcreteHandlerC handles the request: " << request << std::endl;  } else {  Handler::HandleRequest(request);  }  }  
};  int main() {  std::shared_ptr<Handler> handlerA = std::make_shared<ConcreteHandlerA>();  std::shared_ptr<Handler> handlerB = std::make_shared<ConcreteHandlerB>();  std::shared_ptr<Handler> handlerC = std::make_shared<ConcreteHandlerC>();  // 设置责任链  handlerA->setSuccessor(handlerB);  handlerB->setSuccessor(handlerC);  // 发送请求  handlerA->HandleRequest("A");  handlerA->HandleRequest("B");  handlerA->HandleRequest("C");  handlerA->HandleRequest("D");  return 0;  
}

在上述示例中,Handler是抽象处理器类,定义了处理请求的方法。ConcreteHandlerA、ConcreteHandlerB和ConcreteHandlerC是具体处理器类,分别处理请求A、B和C。在创建这些处理器对象时,按照责任链的顺序将它们连接起来。在main函数中,程序创建了一个责任链,将请求依次发送给处理器A、B、C,如果没有任何处理器能够处理请求,则请求不会被处理。

总之,责任链模式是一种非常有用的设计模式,它可以将请求和处理请求的对象解耦,从而提高系统的灵活性和可扩展性。在实际应用中,它可以帮助我们解决很多复杂的问题,提高系统的处理能力和吞吐量,同时也提高了代码的可维护性和可读性。

5、Qt事件传播机制
QT源码:事件系统
QT的事件处理系统同样用到了事件处理系统,其中事件通过事件队列发送到对应的对象,每个对象都可以处理该事件,如果该对象无法处理,将会发给下一个对象。

以下是 QAppliaction 发送鼠标事件给 QWidget 的部分源码:

//接收鼠标事件的对象w
QWidget* w = static_cast<QWidget *>(receiver);
//鼠标事件e
QMouseEvent* mouse = static_cast<QMouseEvent*>(e);......while (w) {//创建一个新的鼠标事件对象,用于在对象树中传播鼠标事件QMouseEvent me(mouse->type(), relpos, mouse->windowPos(), mouse->globalPos(),mouse->button(), mouse->buttons(), mouse->modifiers(), mouse->source());......//如果鼠标事件被接受,打破循环eventAccepted = (w == receiver ? mouse : &me)->isAccepted();if (res && eventAccepted)break;......//如果鼠标事件未被接受,将w设置为w的父组件,继续循环w = w->parentWidget();
}

可以看出, QApplication 将鼠标事件沿着对象树传递,直到有一个对象能够处理为止,符合责任链模式的思想,其中:

QObject:Handler(处理者),定义一个处理鼠标事件的接口。
QWidgt:ConcreteHandler(具体处理者),实现了 QObject 的接口,判断自己是否能够处理鼠标事件,如果不能将请求传递给父类 QWidget。
QMouseEvent:Request(请求),封装了鼠标事件的信息。
QAppliaction:客户端,是请求的发起者。

以上即可展现责任链模式在QT中应用。如果在意细节,可以看下方第6条,否则,后面不用看!

6、Qt事件传播机制 具体细节

事件传播机制和对象树机制共同构成了Qt中对象的一种管理方式和事件的一种传播方式。通过在对象之间建立处理请求的责任链,可以使请求的处理与请求的发起者解耦,提高代码的可扩展性和可维护性。另外,Qt还提供了QObject::installEventFilter方法,即可以安装一个事件过滤器来处理事件。事件过滤器是一个单独的对象,它可以拦截并处理一个或多个对象的事件。因此,事件过滤器也可以看作责任链模式中的一环。

下面给出Qt源码中如何实现事件传播机制,并且体现出责任链模式的一个示例。注意,这个示例省略了比较多的细节,但作为示例去描述Qt源码中如何体现责任链模式,应该是勉强足够的。

#include <iostream>enum EventType { UnknownEvent, MouseButtonPressEvent };class QEvent {
public:explicit QEvent(EventType type) : _type(type), _accepted(false) {}virtual ~QEvent() {}EventType type() const { return _type; }void accept() { _accepted = true; }void ignore() { _accepted = false; }bool isAccepted() const { return _accepted; }private:EventType _type;bool _accepted;
};class QObject {
public:virtual ~QObject() {}virtual bool event(QEvent *event) {// 默认实现,不处理任何事件return false;}virtual bool eventFilter(QObject *, QEvent *) {// 默认实现,不处理任何事件return false;}
};class QWidget : public QObject {
public:virtual ~QWidget() {}bool event(QEvent *event) override {switch (event->type()) {case MouseButtonPressEvent:mousePressEvent(event);return true;default:return QObject::event(event);}}virtual void mousePressEvent(QEvent *event) {std::cout << "QWidget: Mouse button press event\n";event->accept();}
};

通过上面的示例,可以看到,QObjectQWidgetQEvent三个类的设计和实现,体现了责任链模式。

QWidget,继承自QObject,重写了event()方法,专门处理用户界面事件。例如,当按键事件发生,我们可以获取按下的键码,然后调用事件的accept()方法表示处理完成,从而阻止事件继续向上传递。如果QWidget无法处理事件,它会将事件传递给父对象。

QEvent是所有事件的基类,每个事件有独特的类型标识符。QEvent类还提供了isAccepted()accept()ignore()方法,标记事件是否被接受和处理。一旦事件被处理,我们可以通过调用accept()方法停止事件的传递,避免重复处理。

作为所有Qt对象的基类,QObject通过提供event()eventFilter()两个虚函数,构建了事件处理的基础。其中event()负责处理自身接收到的事件,eventFilter()则处理需要过滤的事件。如果事件未被处理,它会被传递给父对象,形成责任链。那么传递给父对象的逻辑,在哪里呢?往QWidget::event()方法里打断点调试就会发现,调用栈会经过QApplication::notify(QObject *receiver, QEvent *e),也就是说,事件的分发回经过里面QApplication::notify。切换到这个方法的调用点查看源代码,可以看到这么一段逻辑:

bool QApplication::notify(QObject* receiver, QEvent* e)
{//其他逻辑//...bool res = false;switch (e->type()) {//处理其他事件类型//...case QEvent::MouseButtonPress:case QEvent::MouseButtonRelease:case QEvent::MouseButtonDblClick:case QEvent::MouseMove:{QWidget* w = static_cast<QWidget*>(receiver);QMouseEvent* mouse = static_cast<QMouseEvent*>(e);QPoint relpos = mouse->pos();if (e->spontaneous()) {if (e->type() != QEvent::MouseMove)QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos);// ### Qt 5 These dynamic tool tips should be an OPT-IN feature. Some platforms// like OS X (probably others too), can optimize their views by not// dispatching mouse move events. We have attributes to control hover,// and mouse tracking, but as long as we are deciding to implement this// feature without choice of opting-in or out, you ALWAYS have to have// tracking enabled. Therefore, the other properties give a false sense of// performance enhancement.if (e->type() == QEvent::MouseMove && mouse->buttons() == 0&& w->rect().contains(relpos)) { // Outside due to mouse grab?d->toolTipWidget = w;d->toolTipPos = relpos;d->toolTipGlobalPos = mouse->globalPos();QStyle* s = d->toolTipWidget->style();int wakeDelay = s->styleHint(QStyle::SH_ToolTip_WakeUpDelay, 0, d->toolTipWidget, 0);d->toolTipWakeUp.start(d->toolTipFallAsleep.isActive() ? 20 : wakeDelay, this);}}bool eventAccepted = mouse->isAccepted();QPointer<QWidget> pw = w;while (w) {QMouseEvent me(mouse->type(), relpos, mouse->windowPos(), mouse->globalPos(),mouse->button(), mouse->buttons(), mouse->modifiers(), mouse->source());me.spont = mouse->spontaneous();me.setTimestamp(mouse->timestamp());QGuiApplicationPrivate::setMouseEventFlags(&me, mouse->flags());// throw away any mouse-tracking-only mouse eventsif (!w->hasMouseTracking()&& mouse->type() == QEvent::MouseMove && mouse->buttons() == 0) {// but still send them through all application event filters (normally done by notify_helper)d->sendThroughApplicationEventFilters(w, w == receiver ? mouse : &me);res = true;}else {w->setAttribute(Qt::WA_NoMouseReplay, false);res = d->notify_helper(w, w == receiver ? mouse : &me);e->spont = false;}eventAccepted = (w == receiver ? mouse : &me)->isAccepted();if (res && eventAccepted)break;if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))break;relpos += w->pos();w = w->parentWidget();}mouse->setAccepted(eventAccepted);if (e->type() == QEvent::MouseMove) {if (!pw)break;w = static_cast<QWidget*>(receiver);relpos = mouse->pos();QPoint diff = relpos - w->mapFromGlobal(d->hoverGlobalPos);while (w) {if (w->testAttribute(Qt::WA_Hover) &&(!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {QHoverEvent he(QEvent::HoverMove, relpos, relpos - diff, mouse->modifiers());d->notify_helper(w, &he);}if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))break;relpos += w->pos();w = w->parentWidget();}}d->hoverGlobalPos = mouse->globalPos();}break;//处理其他事件类型//...}return res;
}

我们在这里只关心鼠标事件(QEvent::MouseButtonPress,QEvent::MouseButtonRelease,QEvent::MouseButtonDblClick,QEvent::MouseMove:)的处理。下面分析一下关键的程序段:

1. 在处理鼠标事件时,首先获取当前QWidget对象w

QWidget* w = static_cast<QWidget *>(receiver);

2. 把事件循环遍历至最高级父窗口或直到一个处理了事件的窗口。在此过程中,对于没有成功处理鼠标事件的窗口,事件会沿着窗口的父链继续传递。

while (w) {// 将事件发送给QWidget对象w,尝试让其处理// ...// 当事件已经被接收并得到处理,跳出循环if (res && eventAccepted)break;// 当到达顶层窗口或当前窗口标记为Qt::WA_NoMousePropagation (无鼠标事件传递)时,跳出循环if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))break;// 获取父窗口,在while循环下一轮尝试让父窗口去处理w = w->parentWidget();
}

在这个while循环中,就会不断地去获取父对象,尝试让其处理。事件得到处理,或者当到达顶层窗口,或者当前窗口标记为Qt::WA_NoMousePropagation (无鼠标事件传递)时,跳出循环。这里就体现出了事件处理的传递链。

可以继续解析上面的程序示例中,"将事件发送给QWidget对象w,尝试让其处理"部分没有展示出的代码:

1. 根据收到的原始鼠标事件(mouse)创建一个新的鼠标事件(me),并使用正确的相对位置(relpos)更新它。同时设置一些其他属性,如是否自发、时间戳和鼠标事件标志。

QMouseEvent me(mouse->type(), relpos, mouse->windowPos(), mouse->globalPos(),mouse->button(), mouse->buttons(), mouse->modifiers(), mouse->source());
me.spont = mouse->spontaneous();
me.setTimestamp(mouse->timestamp());
QGuiApplicationPrivate::setMouseEventFlags(&me, mouse->flags());

2. 对于没有鼠标跟踪并且是无按钮按下的鼠标移动事件(仅用于鼠标跟踪的事件),忽略这个事件,并将其传递给所有应用程序事件过滤器。设置结果变量res = true表示事件已被处理。

if (!w->hasMouseTracking()&& mouse->type() == QEvent::MouseMove && mouse->buttons() == 0) {// but still send them through all application event filters (normally done by notify_helper)d->sendThroughApplicationEventFilters(w, w == receiver ? mouse : &me);res = true;
}

3. 否则,尝试将mouseme事件传递给QWidget对象(视情况而定)。更新事件的自发属性为false

else {w->setAttribute(Qt::WA_NoMouseReplay, false);res = d->notify_helper(w, w == receiver ? mouse : &me);e->spont = false;
}

4. 检查事件是否已被接受。这个步骤会影响后续窗口的事件传递。

eventAccepted = (w == receiver ? mouse : &me)->isAccepted();

综上,QObject作为事件处理接口,QWidget实现具体的处理逻辑,而QEvent则扮演了请求的角色,QApplication参与了事件的分发和向上传递。这几个类的协作为Qt提供了一种高效、灵活且可扩展的事件处理机制,帮助开发者轻松处理各种事件和场景。

总结

至此,我们已经解析了Qt的对象树机制,构建在对象树机制之上的事件传递机制,以及它们背后的设计思想。在后续的文章中,我们可能还会继续解析Qt源码中事件机制相关的设计模式。事件机制确实是Qt中的核心机制之一,我们能够深挖的东西,恐怕还有很多。

                        
原文链接:https://blog.csdn.net/buhuiCyvyan/article/details/138793057

原文链接:https://zhuanlan.zhihu.com/p/631330647

相关文章:

事件传播机制 与 责任链模式

1、基本概念 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;将请求沿着处理链传递&#xff0c;直到有一个对象能够处理为止。 2、实现的模块有&#xff1a; Handler&#xff08;处理者&#xff09;&#xff1a;定义一个…...

uniapp 展示地图,并获取当前位置信息(精确位置)

使用uniapp 提供的map标签 <map :keymapIndex class"container" :latitude"latitude" :longitude"longitude" ></map> 页面初始化的时候&#xff0c;获取当前的位置信息 created() {let that thisuni.getLocation({type: gcj02…...

Autosar实践——诊断配置(DaVinci Configuration)

文章目录 一、制作诊断数据库文件(cdd文件)二、导入诊断数据库文件并修复模块生成的问题三、创建SWC CS接口Service Ports四、创建Service Runnable五、关联SWC和DCM/DEM模块六、RTE代码编写22服务2E服务31服务DTC Set/Get关联文章列表: Autosar-软件架构 Autosar诊断-简介和…...

植物大战僵尸杂交版全新版v2.1解决全屏问题

文章目录 &#x1f68b;一、植物大战僵尸杂交版❤️1. 游戏介绍&#x1f4a5;2. 如何下载《植物大战僵尸杂交版》 &#x1f680;二、解决最新2.1版的全屏问题&#x1f308;三、画质增强以及减少闪退 &#x1f68b;一、植物大战僵尸杂交版 《植物大战僵尸杂交版》是一款在原版《…...

【code-server】Code-Server 安装部署

Code-Server 安装部署 1.环境准备 可以参考 https://coder.com/docs/code-server/install code-server的安装流程进行安装&#xff0c;主机环境是 Centos7 建议使用 docker 方式进行安装&#xff0c;可能会出现如下报错&#xff0c;需要升级 GNC 的版本&#xff0c;由于影响较…...

博客摘录「 YOLOv5模型剪枝压缩」2024年5月11日

添加L1正则来约束BN层系数 语义边缘检测和语义分割的关系调研结果为&#xff0c;语义信息可以用来增强语义分割的效果&#xff0c;也有一定的优点和采用理由&#xff0c;但此类论文的数量并不是很多&#xff0c;语义分割的多数方法还是使用深度学习直接做像素分类。在对比两者…...

HttpSecurity

这是Spring Security提供的配置类, 用户保护基于HTTP的请求 ,通过HttpSecurity可以设置各种安全设置{认证,授权,CSRF保护,会话管理,异常处理} 主要功能和配置: 1.认证配置: 配置登录和登出功能,指定登录页面、登录处理 URL、成功和失败处理器等。配置认证方式,如表单登录、…...

Mysql union语句

开源项目SDK&#xff1a;https://github.com/mingyang66/spring-parent 个人文档&#xff1a;https://mingyang66.github.io/raccoon-docs/#/ mysql union操作符用于连接两个以上的select语句的结果组合到一个结果集&#xff0c;并去除重复的行&#xff0c;每个select语句的雷叔…...

MySQL之高级特性(四)

高级特性 查询缓存 什么情况下查询缓存能发挥作用 并不是什么情况下查询缓存都会提高系统性能的。缓存和失效都会带来额外的消耗&#xff0c;所以只有当缓存带来的资源节约大于本身的资源消耗时才会给系统带来性能提升。这跟具体的服务器压力模型有关。理论上&#xff0c;可…...

roles安装wordpress

debug模块 1.如何查看ansible-playbook执行过程中产生的具体信息 vim test3.yaml --- - hosts: allremote_user: roottasks:- name: lsshell: ls /rootregister: var_stdout # register:将var_stdout注册为变量- name: debugdebug:var: var_stdout # 查看所有的输出信息#var…...

【Python高级编程】饼状图中autopct和startangle用来做什么的

autopct 设置饼状图中每个扇区的百分比标签。接受一个格式字符串&#xff0c;用于指定如何格式化标签。默认值为 %.1f%%&#xff0c;表示保留一位小数的百分比格式。可以设置为 None 以禁用百分比标签。 startangle 设置饼状图中第一个扇区的起始角度。角度以顺时针方向从 3…...

【ARM Coresight Debug 系列 -- ARMv8/v9 Watchpoint 软件实现地址监控详细介绍】

请阅读【嵌入式开发学习必备专栏 】 文章目录 ARMv8/v9 Watchpoint exceptionsWatchpoint 配置信息读取Execution conditionsWatchpoint data address comparisonsSize of the data accessWatchpoint 软件配置流程Watchpoint Type 使用介绍WT, Bit [20]: Watchpoint TypeLBN, B…...

jvm工具-jps、jstat、jmap、jstack

一、jps jps -v 【输出进程启动参数】 [rootVM-8-2-centos ~]# jps -v 12401 Jps -Dapplication.home/usr/local/jdk1.8.0_241 -Xms8m 16964 jar 其他参考 Java八股文必看&#xff0c;入门到深入理解jvm虚拟机之基础故障指令【jps&#xff0c;jstate...】-CSDN博客 二、j…...

LVS负载均衡群集+NAT部署

目录 一、企业群集应用概述 1.1 群集的含义 1.2 企业群集分类 二、负载均衡群集架构和工作模式 2.1负载均衡的结构 2.2负载均衡群集工作模式分析 三、LVS虚拟服务器 3.1Linux Virtual Server 3.2LVS必要的工具 3.3LVS的负载调度算法 一、企业群集应用概述 1.1 群集的…...

使用 Oracle SQL Developer 导入数据

使用 Oracle SQL Developer 导入数据 1. 导入过程 1. 导入过程 选择要导入数据的表&#xff0c; 然后单击右键&#xff0c;选择"导入数据"&#xff0c; 浏览本地文件&#xff0c;选择正确的工作表&#xff0c; 按默认&#xff0c; 按默认&#xff0c; 根据情况修改&…...

品质主管的面试题目

在品质主管的面试中,面试官可能会提出一系列问题来评估应聘者的经验、技能和专业知识。以下是一些常见的品质主管面试题,你可以提前准备,以更好地展示自己的能力和适应性。 一、自我介绍与背景了解 请简单介绍一下自己,包括教育背景、工作经验等。你在过去的工作经历中,主…...

算法专题总结链接地址

刷力扣的时候会遇到一些总结类型的题解&#xff0c;在此记录&#xff0c;方便自己以后找 前缀和 前缀和https://leetcode.cn/problems/unique-substrings-in-wraparound-string/solutions/432752/xi-fa-dai-ni-xue-suan-fa-yi-ci-gao-ding-qian-zhui-/ 单调栈 单调栈https:…...

Oracle--存储结构

总览 一、逻辑存储结构 二、物理存储结构 1.数据文件 2.控制文件 3.日志文件 4.服务器参数文件 5.密码文件 总览 一、逻辑存储结构 数据块是Oracle逻辑存储结构中的最小的逻辑单位&#xff0c;一个数据库块对应一个或者多个物理块&#xff0c;大小由参数DB_BLOCK_SIZE决…...

【计算机毕业设计】259基于微信小程序的医院综合服务平台

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…...

HP惠普暗影精灵10 OMEN Gaming Laptop 16-wf1xxx原厂Win11系统镜像下载

惠普hp暗影精灵10笔记本电脑16-wf1000TX原装出厂Windows11&#xff0c;恢复开箱状态oem预装系统安装包&#xff0c;带恢复重置还原 适用型号:16-wf1xxx 16-wf1000TX,16-wf1023TX,16-wf1024TX,16-wf1025TX, 16-wf1026TX,16-wf1027TX,16-wf1028TX,16-wf1029TX, 16-wf1030TX,16-…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道

文/法律实务观察组 在债务重组领域&#xff0c;专业机构的核心价值不仅在于减轻债务数字&#xff0c;更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明&#xff0c;合法债务优化需同步实现三重平衡&#xff1a; 法律刚性&#xff08;债…...

C++--string的模拟实现

一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现&#xff0c;其目的是加强对string的底层了解&#xff0c;以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量&#xff0c;…...

EEG-fNIRS联合成像在跨频率耦合研究中的创新应用

摘要 神经影像技术对医学科学产生了深远的影响&#xff0c;推动了许多神经系统疾病研究的进展并改善了其诊断方法。在此背景下&#xff0c;基于神经血管耦合现象的多模态神经影像方法&#xff0c;通过融合各自优势来提供有关大脑皮层神经活动的互补信息。在这里&#xff0c;本研…...

Web APIS Day01

1.声明变量const优先 那为什么一开始前面就不能用const呢&#xff0c;接下来看几个例子&#xff1a; 下面这张为什么可以用const呢&#xff1f;因为复杂数据的引用地址没变&#xff0c;数组还是数组&#xff0c;只是添加了个元素&#xff0c;本质没变&#xff0c;所以可以用con…...