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

D-Pointer(Pimpl)设计模式(指向实现的指针)

Qt 的 D-Pointer(Pimpl)设计模式

1. Pimpl 模式简介

Pimpl(Pointer to Implementation)是一种设计模式,用于将类的接口与实现分离,从而隐藏实现细节,降低编译依赖,提高代码的可维护性和可扩展性。这种模式在 Qt 中被称为 D-Pointer,广泛应用于 Qt 框架中。

2. Pimpl 模式的优势
  • 隐藏实现细节:通过将私有成员变量和方法放在一个单独的类中,头文件中只包含一个指向该类的指针,从而隐藏了实现细节。
  • 降低编译依赖:修改私有实现不会影响到头文件,因此不会引起重新编译。
  • 提高编译速度:由于头文件中只包含一个指针,编译依赖减少,编译速度提升。
  • 保持稳定的 ABI:即使内部实现发生变化,只要接口保持不变,二进制接口(ABI)也保持稳定。
3. Qt 中的 D-Pointer 实现

在 Qt 中,D-Pointer 的实现主要通过以下宏来完成:

  • Q_DECLARE_PRIVATE:在公共类中声明一个指向私有实现类的指针。
  • Q_DECLARE_PUBLIC:在私有实现类中声明一个指向公共类的指针。
  • Q_DQ_Q:在公共类和私有实现类中分别用于访问对方。
4. 实现示例
公共类 ElaApplication
#include <QObject>
#include "ElaApplicationPrivate.h"  // 包含私有实现类的声明class ElaApplication : public QObject {Q_OBJECTQ_DECLARE_PRIVATE(ElaApplication)  // 声明私有实现类指针
public:explicit ElaApplication(QObject *parent = nullptr);~ElaApplication();void setIsEnableMica(bool enable);bool isEnableMica() const;void setMicaImagePath(const QString &path);QString micaImagePath() const;private:ElaApplicationPrivate *d_ptr;  // 指向私有实现类的指针
};
私有实现类 ElaApplicationPrivate
#include "ElaApplication.h"class ElaApplicationPrivate {Q_DECLARE_PUBLIC(ElaApplication)  // 声明公共类指针
public:ElaApplicationPrivate(ElaApplication *q);~ElaApplicationPrivate();bool isEnableMica;QString micaImagePath;private:ElaApplication *q_ptr;  // 指向公共类的指针
};
实现文件 ElaApplication.cpp
#include "ElaApplication.h"
#include "ElaApplicationPrivate.h"ElaApplication::ElaApplication(QObject *parent): QObject(parent), d_ptr(new ElaApplicationPrivate(this)) {Q_D(ElaApplication);  // 使用 Q_D 宏获取私有实现指针d->isEnableMica = false;  // 初始化私有成员
}ElaApplication::~ElaApplication() {delete d_ptr;  // 删除私有实现
}void ElaApplication::setIsEnableMica(bool enable) {Q_D(ElaApplication);  // 使用 Q_D 宏获取私有实现指针d->isEnableMica = enable;
}bool ElaApplication::isEnableMica() const {Q_D(const ElaApplication);  // 使用 Q_D 宏获取私有实现指针return d->isEnableMica;
}void ElaApplication::setMicaImagePath(const QString &path) {Q_D(ElaApplication);  // 使用 Q_D 宏获取私有实现指针d->micaImagePath = path;
}QString ElaApplication::micaImagePath() const {Q_D(const ElaApplication);  // 使用 Q_D 宏获取私有实现指针return d->micaImagePath;
}
5. 总结
  • Pimpl 模式:通过将实现细节隐藏在私有类中,减少编译依赖,提高代码的可维护性和可扩展性。
  • Qt 的 D-Pointer:通过 Q_DECLARE_PRIVATEQ_DECLARE_PUBLICQ_D 等宏,Qt 提供了一种简洁的方式来实现 Pimpl 模式。
  • 应用场景:Pimpl 模式在需要隐藏实现细节、减少编译依赖和保持稳定的 ABI 的场景中非常有用。

希望这些信息能帮助你更好地理解 Qt 的 D-Pointer(Pimpl)设计模式!


示例代码

公共类 Car 的头文件
#include <QObject>class CarPrivate;  // 前置声明私有类class Car : public QObject {Q_OBJECT// Q_DECLARE_PRIVATE 宏展开// 原始宏定义:// #define Q_DECLARE_PRIVATE(Class) \//     inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } \//     inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr)); } \//     friend class Class##Private;inline CarPrivate* d_func() { return reinterpret_cast<CarPrivate *>(qGetPtrHelper(d_ptr)); }  // 获取非const的私有实现inline const CarPrivate* d_func() const { return reinterpret_cast<const CarPrivate *>(qGetPtrHelper(d_ptr)); }  // 获取const的私有实现friend class CarPrivate;  // 声明私有实现类为友元类public:Car(QObject *parent = nullptr);~Car();void startEngine();  // 公共方法private:CarPrivate *d_ptr;  // 指向私有实现类的指针
};
私有实现类 CarPrivate 的头文件
#include "Car.h"class CarPrivate {// Q_DECLARE_PUBLIC 宏展开// 原始宏定义:// #define Q_DECLARE_PUBLIC(Class) \//     Class *q_ptr; \//     inline Class *q_func() { return q_ptr; } \//     inline const Class *q_func() const { return q_ptr; }Car *q_ptr;  // 指向公共类的指针inline Car *q_func() { return q_ptr; }  // 获取非const的公共类指针inline const Car *q_func() const { return q_ptr; }  // 获取const的公共类指针public:CarPrivate(Car *q) : q_ptr(q) {}bool engineStarted = false;  // 私有成员变量
};
实现文件 Car.cpp
#include "Car.h"
#include "CarPrivate.h"// 构造函数
Car::Car(QObject *parent) : QObject(parent), d_ptr(new CarPrivate(this)) {// 初始化私有类
}// 析构函数
Car::~Car() {delete d_ptr;  // 删除私有类
}// startEngine 方法
void Car::startEngine() {// Q_D 宏展开// 原始宏定义:// #define Q_D(Class) Class##Private *const d = d_func()CarPrivate *const d = d_func();  // 获取私有实现指针d->engineStarted = true;  // 修改私有成员变量
}

详细解释

1. Q_DECLARE_PRIVATE
// 原始宏定义:
// #define Q_DECLARE_PRIVATE(Class) \
//     inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } \
//     inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr)); } \
//     friend class Class##Private;inline CarPrivate* d_func() { return reinterpret_cast<CarPrivate *>(qGetPtrHelper(d_ptr)); }  // 获取非const的私有实现
inline const CarPrivate* d_func() const { return reinterpret_cast<const CarPrivate *>(qGetPtrHelper(d_ptr)); }  // 获取const的私有实现
friend class CarPrivate;  // 声明私有实现类为友元类
  • d_func():提供了一个方法来访问私有实现类的指针。
  • friend class CarPrivate:将私有实现类声明为友元类,允许它访问公共类的私有成员。
2. Q_DECLARE_PUBLIC
// 原始宏定义:
// #define Q_DECLARE_PUBLIC(Class) \
//     Class *q_ptr; \
//     inline Class *q_func() { return q_ptr; } \
//     inline const Class *q_func() const { return q_ptr; }Car *q_ptr;  // 指向公共类的指针
inline Car *q_func() { return q_ptr; }  // 获取非const的公共类指针
inline const Car *q_func() const { return q_ptr; }  // 获取const的公共类指针
  • q_ptr:在私有实现类中声明一个指向公共类的指针。
  • q_func():提供了一个方法来访问公共类的指针。
3. Q_D
// 原始宏定义:
// #define Q_D(Class) Class##Private *const d = d_func()CarPrivate *const d = d_func();  // 获取私有实现指针
  • Q_D:简化代码,通过 d_func() 获取私有实现类的指针,并将其存储在局部变量 d 中。

完整的示例代码

公共类 Car 的头文件
#include <QObject>class CarPrivate;  // 前置声明私有类class Car : public QObject {Q_OBJECT// Q_DECLARE_PRIVATE 宏展开inline CarPrivate* d_func() { return reinterpret_cast<CarPrivate *>(qGetPtrHelper(d_ptr)); }  // 获取非const的私有实现inline const CarPrivate* d_func() const { return reinterpret_cast<const CarPrivate *>(qGetPtrHelper(d_ptr)); }  // 获取const的私有实现friend class CarPrivate;  // 声明私有实现类为友元类public:Car(QObject *parent = nullptr);~Car();void startEngine();  // 公共方法private:CarPrivate *d_ptr;  // 指向私有实现类的指针
};
私有实现类 CarPrivate 的头文件
#include "Car.h"class CarPrivate {// Q_DECLARE_PUBLIC 宏展开Car *q_ptr;  // 指向公共类的指针inline Car *q_func() { return q_ptr; }  // 获取非const的公共类指针inline const Car *q_func() const { return q_ptr; }  // 获取const的公共类指针public:CarPrivate(Car *q) : q_ptr(q) {}bool engineStarted = false;  // 私有成员变量
};
实现文件 Car.cpp
#include "Car.h"
#include "CarPrivate.h"// 构造函数
Car::Car(QObject *parent) : QObject(parent), d_ptr(new CarPrivate(this)) {// 初始化私有类
}// 析构函数
Car::~Car() {delete d_ptr;  // 删除私有类
}// startEngine 方法
void Car::startEngine() {// Q_D 宏展开CarPrivate *const d = d_func();  // 获取私有实现指针d->engineStarted = true;  // 修改私有成员变量
}

总结

  • d_ptr:通过 Q_DECLARE_PRIVATE 宏声明,是一个指向私有实现类的指针。
  • d_func():通过 Q_DECLARE_PRIVATE 宏定义,用于获取私有实现类的指针。
  • Q_D:简化代码,通过 d_func() 获取私有实现类的指针,并存储在局部变量 d 中。

1. Q_DECLARE_PRIVATE 宏的定义

Q_DECLARE_PRIVATE 宏的定义如下:

#define Q_DECLARE_PRIVATE(Class) \inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } \inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr)); } \friend class Class##Private;

2. 宏的展开

假设我们有一个类 Car,其私有实现类为 CarPrivate。使用 Q_DECLARE_PRIVATE(Car) 宏后,代码会展开为:

inline CarPrivate* d_func() { return reinterpret_cast<CarPrivate *>(qGetPtrHelper(d_ptr)); }  // 获取非const的私有实现
inline const CarPrivate* d_func() const { return reinterpret_cast<const CarPrivate *>(qGetPtrHelper(d_ptr)); }  // 获取const的私有实现
friend class CarPrivate;  // 声明私有实现类为友元类

3. d_ptr 的作用

Q_DECLARE_PRIVATE 宏中,d_ptr 是一个特定的变量名,它被用来存储指向私有实现类的指针。Q_DECLARE_PRIVATE 宏生成的代码依赖于 d_ptr,因为它假设类中有一个名为 d_ptr 的成员变量。

4. 如果将 d_ptr 改为 fadsfdas_ptr

如果你将 d_ptr 改为 fadsfdas_ptrQ_DECLARE_PRIVATE 宏生成的代码将无法正确工作,因为宏生成的代码仍然会尝试访问 d_ptr,而不是 fadsfdas_ptr

修改后的代码
class Car : public QObject {Q_OBJECT// Q_DECLARE_PRIVATE 宏展开inline CarPrivate* d_func() { return reinterpret_cast<CarPrivate *>(qGetPtrHelper(d_ptr)); }  // 获取非const的私有实现inline const CarPrivate* d_func() const { return reinterpret_cast<const CarPrivate *>(qGetPtrHelper(d_ptr)); }  // 获取const的私有实现friend class CarPrivate;  // 声明私有实现类为友元类public:Car(QObject *parent = nullptr);~Car();void startEngine();  // 公共方法private:CarPrivate *fadsfdas_ptr;  // 指向私有实现类的指针
};
问题
  • d_func() 方法仍然尝试访问 d_ptr,但 d_ptr 不存在。
  • Q_DECLARE_PRIVATE 宏生成的代码依赖于 d_ptr,而不是 fadsfdas_ptr

5. 自定义宏

如果你需要使用不同的变量名(例如 fadsfdas_ptr),你需要手动实现类似 Q_DECLARE_PRIVATE 的功能。这可以通过自定义宏来完成,但不推荐,因为这会增加代码的复杂性和维护难度。

自定义宏
#define Q_DECLARE_PRIVATE_EX(Class, PtrName) \inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(PtrName)); } \inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(PtrName)); } \friend class Class##Private;class Car : public QObject {Q_OBJECTQ_DECLARE_PRIVATE_EX(Car, fadsfdas_ptr)  // 使用自定义宏public:Car(QObject *parent = nullptr);~Car();void startEngine();  // 公共方法private:CarPrivate *fadsfdas_ptr;  // 指向私有实现类的指针
};

6. 详细说明

(1)Q_DECLARE_PRIVATE 宏的依赖

Q_DECLARE_PRIVATE 宏依赖于 d_ptr,因为它假设类中有一个名为 d_ptr 的成员变量。这个变量名是固定的,宏生成的代码会直接使用它。

(2)d_func() 方法

d_func() 方法通过 qGetPtrHelper(d_ptr) 提取 d_ptr 的原始指针,并将其转换为 CarPrivate * 类型。如果 d_ptr 不存在,d_func() 方法将无法正确工作。

(3)friend class CarPrivate

friend class CarPrivate 声明私有实现类为友元类,允许它访问公共类的私有成员。这个声明与 d_ptr 的名字无关,但它是 Q_DECLARE_PRIVATE 宏的一部分。

7. 总结

  • Q_DECLARE_PRIVATE 宏依赖于 d_ptr:它生成的代码假设类中有一个名为 d_ptr 的成员变量。
  • 改变变量名会导致问题:如果将 d_ptr 改为其他名称(例如 fadsfdas_ptr),宏生成的代码将无法正确工作。
  • 推荐使用默认的 d_ptr:为了保持代码的一致性和可维护性,建议使用默认的 d_ptr

相关文章:

D-Pointer(Pimpl)设计模式(指向实现的指针)

Qt 的 D-Pointer&#xff08;Pimpl&#xff09;设计模式 1. Pimpl 模式简介 Pimpl&#xff08;Pointer to Implementation&#xff09;是一种设计模式&#xff0c;用于将类的接口与实现分离&#xff0c;从而隐藏实现细节&#xff0c;降低编译依赖&#xff0c;提高代码的可维护…...

XA协议和Tcc

基于 XA 协议的两阶段提交 (2PC)。这是一种分布式事务协议&#xff0c;旨在保证在多个参与者&#xff08;通常是不同的数据库或资源管理器&#xff09;共同参与的事务中&#xff0c;所有参与者要么都提交事务&#xff0c;要么都回滚事务&#xff0c;从而维护数据的一致性。 你…...

我们该如何使用DeepSeek帮我们减负?

在当今信息爆炸的时代&#xff0c;如何快速获取、筛选和分析信息已经成为各行各业的重要能力。而DeepSeek作为一种先进的智能搜索和信息挖掘工具&#xff0c;能够帮助用户快速找到所需的信息&#xff0c;并从海量数据中提取出有用的洞见。在这篇博文中&#xff0c;我们将深入探…...

25.5.13

感觉很久没有写算法题了&#xff0c;先来个滑动队列模板题试试水&#xff0c;就是用双端队列来实现会很方便&#xff0c;拿结构体来记录是第几个数和数的值即可&#xff0c;再定义两个双端队列&#xff0c;一个使他的值单调递增一个使他的值单调递减 使队头元素为最大值或者是最…...

软件测试——面试八股文(入门篇)

今天给大家分享软件测试面试题入门篇&#xff0c;看看大家能答对几题 一、 请你说一说测试用例的边界 参考回答&#xff1a; 边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法。通常边界值分析法是作为对等价类划分法的补充&#xff0c;这种情况下&#xff…...

脑机接口技术:开启人类与机器融合的新时代

摘要 脑机接口&#xff08;BCI&#xff09;技术作为一项前沿科技&#xff0c;正在逐步打破人类与机器之间的沟通障碍&#xff0c;为医疗、娱乐、教育等多个领域带来前所未有的变革。本文将详细介绍脑机接口技术的基本原理、发展现状、应用场景以及面临的挑战和未来发展趋势&…...

当三维地理信息遇上气象预警:电网安全如何实现“先知先觉”?

极端天气频发的当下&#xff0c;一场台风、一次暴雨就可能让电力系统陷入瘫痪。但你知道吗&#xff1f;如今的电网已能通过三维地理信息与气象数据的深度融合&#xff0c;在灾害来临前精准锁定风险&#xff0c;甚至将停电事故减少七成以上。这背后&#xff0c;正是国网电力空间…...

C++ string数据查找、string数据替换、string子串获取

string查找示例见下&#xff0c;代码见下&#xff0c;以及对应运行结果见下&#xff1a; #include<iostream>using namespace std;int main() {// 1string s1 "hellooooworld";cout << s1.find("oooo") << endl;// 2cout << (in…...

2025.5.13山东大学软件学院计算机图形学期末考试回忆版本

2025.5.13山东大学软件学院计图期末考试回忆版本 学院&#xff1a;软件学院 老师&#xff1a;周元峰、魏广顺 一、简述题&#xff08;2024原题一&#xff09; 1.图形绘制流水线的组成和作用 2.双缓冲机制是什么&#xff0c;有什么作用&#xff1f; 3.Delaunay三角化的四条…...

思极地图使用

思极地图api文档&#xff1a;思极地图开放平台 | 思极地图API SDK 思极地图SDK: <script src"https://map.sgcc.com.cn/maps?v3.0.0"></script> <script src"https://map.sgcc.com.cn/products/js-sdk/v3/assets/js/jquery-1.11.1.min.js&quo…...

Fiori学习专题四十一:表单控件

上节课我们学习了一些单一控件的使用&#xff0c;但是我们发现在页面内每个控件都占用了一行&#xff0c;这样子就显得不太好看&#xff0c;这节课我们引入一个表单控件来美化一下这个页面。 1.学习表单控件FORM之前我们先了解下哪些情况会使用到表单控件&#xff0c;最常见的场…...

基于STM32、HAL库的TDA7719TR音频接口芯片驱动程序设计

一、简介: TDA7719TR 是 NXP Semiconductors 推出的高性能音频处理芯片,专为汽车音响系统设计。它集成了 AM/FM 收音机调谐器、音频处理和音量控制功能,支持 I2C 控制接口,非常适合与 STM32 微控制器配合使用。 二、硬件接口: 典型的 STM32L4 与 TDA7719TR 硬件连接如下…...

Baklib智能云平台加速企业数据治理

Baklib数据治理核心优势 Baklib作为新一代企业级知识中台&#xff0c;其数据治理能力建立在全资产统一管理与智能化处理框架的双重基础之上。通过构建知识中台的核心架构&#xff0c;平台实现了图文、音视频等多模态数据的标准化存储与动态标签体系&#xff0c;有效解决传统管…...

面试中被问到谈谈你对threadlocal的理解

ThreadLocal 的核心理解 1. 基本概念 ThreadLocal 是 Java 提供的线程局部变量机制&#xff0c;用于在多线程环境中为每个线程维护独立的变量副本&#xff0c;实现线程隔离。其核心思想是空间换时间&#xff0c;通过避免共享变量带来的同步开销&#xff0c;提升并发性能。 2…...

Spring Boot 应用中实现基本的 SSE 功能

SSE 技术简介 SSE&#xff08;Server-Sent Events&#xff09;是一种允许服务器主动向客户端推送数据的技术。它基于 HTTP 长连接&#xff0c;使用简单&#xff0c;特别适合实时数据更新场景&#xff0c;如股票行情、新闻推送等。与 WebSocket 相比&#xff0c;SSE 更轻量级&a…...

【2025最新】Windows系统装VSCode搭建C/C++开发环境(附带所有安装包)

文章目录 为什么选择VSCode作为C/C开发工具&#xff1f;一、VSCode安装过程&#xff08;超简单&#xff01;&#xff09;二、VSCode中文界面设置&#xff08;再也不用对着英文发愁&#xff01;&#xff09;三、安装C/C插件&#xff08;编程必备神器&#xff01;&#xff09;四、…...

【MyBatis-8】MyBatis对象关联查询详解:高效处理复杂关系映射

在实际业务开发中&#xff0c;我们经常需要处理对象之间的关联关系&#xff0c;如一对一、一对多、多对多等。MyBatis作为一款优秀的持久层框架&#xff0c;提供了强大的对象关联查询能力。本文将深入探讨MyBatis中各种关联查询的实现方式、适用场景及最佳实践。 1. MyBatis关…...

Java基础(IO)

所有操作都在内存&#xff0c;不能长时间保存&#xff0c;IO主要在硬盘&#xff0c;可以长时间保存。 一、File类 File类被定义为文件和目录路径名的抽象表示形式&#xff0c;这是因为 File 类既可以表示文件也可以表示目录&#xff0c;他们都通过对应的路径来描述。 提供构…...

Trae IDE:AI深度集成的智能开发环境

&#xff08;以高效人机协作重塑编程体验&#xff09; 概述 Trae IDE&#xff08;发音 /treɪ/&#xff09;是一款深度集成AI能力的现代化开发工具&#xff0c;结合传统IDE的完备功能与前沿AI技术&#xff0c;提供智能问答、代码自动补全、跨文件编程及AI Agent驱动的自动化开…...

网站开发过程中样式忽然不显示问题

老规矩&#xff0c;先听故事&#xff1a;今天我开发网站时候遇到一个问题&#xff0c;就开发的这个网站在默认127.0.0.1运行样式有bug显示不出来&#xff0c;之前都可以&#xff0c;就完全一样的代码&#xff0c;之前可以正常运行显示&#xff0c;今天忽然就不行了&#xff0c;…...

双种群进化算法:动态约束处理与资源分配解决约束多目标优化问题

双种群进化算法&#xff1a;动态约束处理与资源分配解决约束多目标优化问题 一、引言 约束多目标优化问题&#xff08;CMOPs&#xff09;在工程设计、资源分配等领域广泛存在&#xff0c;其核心是在满足多个约束条件的同时优化多个目标函数。传统方法往往难以平衡约束满足与目…...

如何在 CentOS 7 虚拟机上配置静态 IP 地址并保持重启后 SSH 连接

在使用 CentOS 7 的虚拟机时&#xff0c;我们通常需要配置静态 IP 地址&#xff0c;以确保在每次虚拟机重启后能够通过 SSH 连接。本文将介绍如何在 CentOS 7 系统中配置静态 IP 地址&#xff0c;并确保配置在系统重启后依然生效。 步骤 1&#xff1a;检查虚拟机网络接口 首先…...

整数和浮点数转换时的精度损失

文章目录 int和float转换时的精度损失float组成解析&#xff08;1&#xff09; 32位浮点数的结构&#xff08;2&#xff09;示例&#xff1a;解析一个浮点数&#xff08;3&#xff09;偏置值的作用&#xff08;4&#xff09; 偏置值为什么是127&#xff1f;&#xff08;5&#…...

Protobuf工具

#region 知识点一 什么是 Protobuf //Protobuf 全称是 protocol - buffers&#xff08;协议缓冲区&#xff09; // 是谷歌提供给开发者的一个开源的协议生成工具 // 它的主要工作原理和我们之前做的自定义协议工具类似 // 只不过它更加的完善&…...

闭包原理与常见陷阱

引言 JavaScript闭包是前端开发中既强大又神秘的概念&#xff0c;它不仅是面试的必考题&#xff0c;更是解决复杂问题的利器。闭包让函数能够记住并访问其创建时的作用域&#xff0c;即使在该函数在其定义环境之外执行。 然而&#xff0c;正如许多强大的工具一样&#xff0c;…...

用 VS Code / PyCharm 编写你的第一个 Python 程序

用ChatGPT做软件测试 编写你的第一个 Python 程序——不只是“Hello, World”&#xff0c;而是构建认知、习惯与未来的起点 “第一行代码&#xff0c;是一个开发者认知世界的方式。” 编程的入门&#xff0c;不只是运行一个字符串输出&#xff0c;更是开始用计算机思维来理解、…...

Linux学习心得问题整理(一)

day01 运维初识 理解云计算运维目的是什么&#xff1f; 搭建云计算更有利于我们在公网环境下方便访问我们服务 节省时间的成本&#xff0c;能随时随地方便调度硬件资源&#xff0c;更容易搭建软件服务 安全可靠&#xff0c;售后期间支持技术支持维护 什么是运维&#xff1f…...

在scala中sparkSQL连接masql并添加新数据

以下是 Scala 中使用 Spark SQL 连接 MySQL 并添加数据的完整代码示例&#xff08;纯文本&#xff09;&#xff1a; 1. 准备连接参数&#xff08;需替换实际信息&#xff09; scala val jdbcUrl "jdbc:mysql://localhost:3306/test_db?useUnicodetrue&characterEnc…...

STM32F103_LL库+寄存器学习笔记22 - 基础定时器TIM实现1ms周期回调

导言 如上所示&#xff0c;STM32F103有两个基本定时器TIM6与TIM7&#xff0c;所谓「基本定时器」&#xff0c;即功能最简单的定时器。 项目地址&#xff1a; github: LL库: https://github.com/q164129345/MCU_Develop/tree/main/stm32f103_ll_library22_Basic_Timer寄存器方…...

.Net HttpClient 使用Json数据

HttpClient 使用Json数据 现代Web项目中&#xff0c;Json是最常用的数据格式。不论是前后端的交互中&#xff0c;还是纯前端项目中&#xff0c;都是如此。因此&#xff0c;.Net HttpClient 能不能更加方便、快捷的处理Json格式数据&#xff0c;也就至关重要了&#xff01; 文末…...

AI时代,如何实现人机共舞?

在科技飞速发展的当下&#xff0c;人工智能&#xff08;AI&#xff09;已不再是科幻作品中的遥远想象&#xff0c;而是深入渗透到我们生活与工作的方方面面。从智能手机中的语音助手&#xff0c;到金融领域的风险预测模型&#xff1b;从医疗影像的智能诊断&#xff0c;到工业生…...

flea-cache使用之Redis哨兵模式接入

Redis哨兵模式接入 1. 参考2. 依赖3. 基础接入3.1 定义Flea缓存接口3.2 定义抽象Flea缓存类3.3 定义Redis客户端接口类3.4 定义Redis客户端命令行3.5 定义哨兵模式Redis客户端实现类3.6 定义Redis哨兵连接池3.7 定义Redis哨兵配置文件3.8 定义Redis Flea缓存类3.9 定义抽象Flea…...

【Docker】Docker环境下快速部署Ollama与Open-WebUI:详细指南

Docker环境下快速部署Ollama与Open-WebUI&#xff1a;详细指南 在本篇文章中&#xff0c;我们将深入探讨如何在Docker中高效部署 Ollama 和 Open-WebUI&#xff0c;并解决在实际使用中常见的问题&#xff0c;确保你的模型服务稳定高效地运行。 一、Ollama 和 Open-WebUI 快速部…...

FFmpeg在Android开发中的核心价值是什么?

FFmpeg 在 Android 开发中的核心价值主要体现在其强大的多媒体处理能力和灵活性上&#xff0c;尤其在音视频编解码、流媒体处理及跨平台兼容性方面具有不可替代的作用。以下是具体分析&#xff1a; --- 1. 强大的音视频编解码能力 - 支持广泛格式&#xff1a;FFmpeg 支持几乎所…...

Java的进制转换

进制知识 Java 中使用不同的前缀表示数据&#xff0c;常见的进制数据有二进制&#xff08;0b&#xff09;、八进制&#xff08;0&#xff09;、十进制&#xff08;无&#xff09;、十六进制&#xff08;0x&#xff09;。 public class Demo1 {public static void main(String…...

SpringBoot中的拦截器

SpringBoot中的拦截器 Filter 典型场景 全局鉴权/接口耗时统计 WebFilter("/*") public class CostFilter implements Filter {Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {long start System.currentTimeMill…...

使用聊天模型和提示模板构建一个简单的 LLM 应用程序

官方教程 官方案例 在上面的链接注册后&#xff0c;请确保设置您的环境变量以开始记录追踪 export LANGSMITH_TRACING"true" export LANGSMITH_API_KEY"..."或者&#xff0c;如果在笔记本中&#xff0c;您可以使用以下命令设置它们 import getpass imp…...

paimon中批和流查看过去的快照的数据及变动的数据

1、批处理 创建表并插入三条数据 CREATE TABLE ws_t (id INT,ts BIGINT,vc INT,PRIMARY KEY (id) NOT ENFORCED ); INSERT INTO ws_t VALUES(2,2,2),(3,3,3),(4,4,4),(5,5,5); --设置执行模式为批处理 RESET execution.checkpointing.interval; SET execution.runtime-mode …...

Linux513 rsync本地传输 跨设备传输 一

ping节点bPing通 仅主机模式不需要设置网关节点a也可以Ping通节点b 同步成功 下载文件夹成功 今日源码 节点a 节点b...

c语言第一个小游戏:贪吃蛇小游戏08(贪吃蛇完结)

贪吃蛇撞墙和想不开咬死自己 #include <curses.h> #include <stdlib.h> struct snake{ int hang; int lie; struct snake *next; }; struct snake food; struct snake *head; struct snake *tail; int key; int dir; #define UP 1 #define DOWN -1 …...

Android Native 之 自定义进程

在Android五层架构中&#xff0c;native层基本上全是c的世界&#xff0c;这些c进程基本上靠android世界的第一个进程init进程创建&#xff0c;init通过rc配置文件&#xff0c;创建了众多的c子进程&#xff0c;也是这众多的c进程&#xff0c;构建了整个android世界的native层。 …...

深度学习 自然语言处理(RNN) day_02

1. 感知机与神经网络 1.1 感知机 生物神经元&#xff1a; 1.1.1 感知机的概念 感知机&#xff08;Perceptron&#xff09;&#xff0c;又称神经元&#xff08;Neuron&#xff0c;对生物神经元进行了模仿&#xff09;是神 经网络&#xff08;深度学习&#xff09;的起源算法&am…...

Kotlin 中的作用域函数

在 Kotlin 中&#xff0c;作用域函数是一组用于在对象上下文中执行代码块的函数。 它们通过简洁的语法实现对对象的操作和逻辑封装。 作用域函数的对比&#xff1a; 1 let 特点&#xff1a; 通过 it 访问对象&#xff0c;需显式使用&#xff1b;返回值是代码块的最后一行结果…...

Linux的SLES系统和其他几大系统之间的区别

✅ SLES 和其他主流 Linux 发行版对比表 特性/发行版SLES (SUSE Linux Enterprise Server)RHEL (Red Hat Enterprise Linux)CentOS / AlmaLinux / RockyUbuntu ServerDebian定位企业级&#xff0c;注重稳定性和支持企业级&#xff0c;行业标准&#xff0c;广泛应用社区版 RHEL…...

上位机学习攻略、步骤和实战路径

目录 &#x1f3af; 一、什么是上位机&#xff1f; &#x1f9ed; 二、学习步骤和路径 第一步&#xff1a;了解基础概念 第二步&#xff1a;掌握通信协议 1. 常见协议&#xff1a; 2. 学习目标&#xff1a; 第三步&#xff1a;熟悉主流上位机软件 可选工具及语言&#…...

【爬虫】DrissionPage-1

官网地址&#xff1a;DrissionPage官网 小需求采集&#xff0c;我喜欢&#xff0c;我要学。 1 介绍 这是用python编写的爬虫自动化工具&#xff0c;将Selenium 和 Requests 的功能巧妙地整合在一起&#xff0c;提供了统一又简单的操作接口。开发者可以在浏览器模式&#xff0…...

API安全

目录 API安全&#xff1a;从威胁到防护的全面解析 引言 一、API安全的定义与重要性 1.1 API安全的核心目标 1.2 API安全的挑战 二、API的常见安全威胁 2.1 身份验证攻击 2.2 中间人攻击&#xff08;MITM&#xff09; 2.3 注入攻击 2.4 安全配置错误 2.5 拒绝服务&…...

UDP和TCP协议

目录 1. UDP协议 1.1. UDP的特性 1.2. UDP的包头 1.3. UDP的三大使用场景和实际例子 1.4. TCP和UDP的区别 2. TCP协议 2.1. TCP包头格式 2.2. TCP包头和UDP包头对比 2.3. TCP协议的特点 2.4. TCP的三次握手&#xff08;连接维护问题&#xff09; 2.5. TCP的四次挥手…...

关于Go语言的开发环境的搭建

1.Go开发环境的搭建 其实对于GO语言的这个开发环境的搭建的过程&#xff0c;类似于java的开发环境搭建&#xff0c;我们都是需要去安装这个开发工具包的&#xff0c;也就是俗称的这个SDK&#xff0c;他是对于我们的程序进行编译的&#xff0c;不然我们写的这个代码也是跑不起来…...

【Bootstrap V4系列】学习入门教程之 组件-导航(Navs)

【Bootstrap V4系列】学习入门教程之 组件-导航&#xff08;Navs&#xff09; 导航&#xff08;Navs&#xff09;一、Base nav二、Available styles 可用样式2.1 Horizontal alignment 水平对齐2.2 Vertical 垂直的2.3 Tabs 表格样式2.4 Pills 胶囊样式2.5 Fill and justify 填…...