《使用Qt Quick从零构建AI螺丝瑕疵检测系统》——2. C++基础:构建程序的坚实骨架

目录

  • 一、概述
    • 1.1 背景介绍:从UI到逻辑
    • 1.2 学习模式:Qt控制台应用
  • 二、C++语法快速入门
    • 2.1 变量、数据类型与注释
    • 2.2 函数与代码封装
    • 2.3 循环与容器:批量处理
  • 三、面向对象编程:封装数据与行为
  • 四、Qt的核心扩展:信号与槽通信
  • 五、总结与展望

一、概述

1.1 背景介绍:从UI到逻辑

在上一篇文章中,我们成功搭建了开发环境,并为“AI螺丝瑕疵检测系统”创建了一个专业、美观的项目骨架。一个软件的UI(用户界面)是它的“面孔”,负责与用户交互;而其C++后端则是它的“大脑”和“骨骼”,负责处理数据、执行复杂逻辑并与硬件通信。

本篇文章的核心任务,就是构建这个强大的“大脑”和“骨骼”。我们将深入C++的世界,但会聚焦于在Qt开发中最常用、最核心的部分。通过本篇的学习,读者将掌握创建后端逻辑、组织代码以及实现对象间通信的基本功,为后续集成真正的视觉算法和硬件交互打下坚实的语言基础。

1.2 学习模式:Qt控制台应用

为了让读者能专注于C++语法本身,暂时不受QML图形界面的干扰,本章的所有示例都将以**Qt控制台应用程序(Qt Console Application)**的形式呈现。这是一种没有图形界面的、纯粹在命令行输出信息的程序,是学习和验证后端逻辑的绝佳工具。
在这里插入图片描述

二、C++语法快速入门

本节面向C++初学者,旨在通过可直接运行的、独立的控制台程序,快速介绍后续章节将会频繁使用的基本语法元素。

2.1 变量、数据类型与注释

【例2-1】 产品信息存储与显示。

变量是程序中用于存储数据的基本单元,可以将其看作是内存中一个带标签的盒子。数据类型则定义了这个“盒子”能装什么类型的东西(如整数、小数、字符串等)以及能对它进行哪些操作。在C++中,定义任何变量都必须首先声明其数据类型。注释用于解释代码,不会被编译器执行。

(1) 基本数据类型: int(整数), double(双精度浮点数), bool(布尔值, true或false)。
(2) Qt常用数据类型: QString(字符串)。在Qt开发中, 推荐使用QString而非C++标准库的std::string,因为它提供了更丰富的功能和更好的Unicode支持。
(3) 注释: 单行注释以//开始,多行注释以/*开始,以*/结束。

使用 Qt Creator 创建一个Qt Console Application程序Demo_2_1_Variables。项目创建完成后,打开main.cpp,修改代码如下:

#include <QCoreApplication>
#include <QDebug>       // 包含Qt的调试输出头文件
#include <QString>      // 包含Qt的字符串类头文件int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// --- 变量定义与初始化 ---int screwCount = 100;double diameter = 5.02;bool isQualified = true;QString batchNumber = "SN20250715-B";// --- 使用qDebug()进行控制台输出 ---qDebug() << "开始进行产品信息检查...";qDebug() << "螺丝数量:" << screwCount << "个";qDebug() << "产品直径:" << diameter << "mm";qDebug() << "质量状态:" << isQualified;qDebug() << "生产批号:" << batchNumber;qDebug() << "检查完毕。";return a.exec();
}

单击 Qt Creator 左下角的绿色“运行”按钮。在下方的“应用程序输出”窗口,可以看到如下结果:

开始进行产品信息检查...
螺丝数量: 100 个
产品直径: 5.02 mm
质量状态: true
生产批号: "SN20250715-B"
检查完毕。

关键代码分析:
(1) #include <QDebug>: 要使用qDebug(),必须包含此头文件。
(2) #include <QString>: QString是Qt中处理文本的专用类,功能强大,完美支持Unicode(包括中文),是Qt开发的首选字符串类型。
(3) 变量定义: 数据类型 variableName = initialValue;是C++定义变量的基本格式。变量名通常使用小驼峰命名法(camelCase)。
(4) qDebug() << ...: 这是qDebug的链式调用语法。它会自动在每个<<分隔的变量之间加上空格,并在最后输出一个换行符,非常便捷。

2.2 函数与代码封装

【例2-2】 封装尺寸检查逻辑。

函数是一段被命名、可重复使用的代码块,用于执行一个特定的任务。随着程序逻辑变得复杂,将不同功能的代码组织成独立的函数,可以极大地提高程序的可读性、可维护性和代码的复用性。一个函数通常有输入(参数)和输出(返回值)。

使用 Qt Creator 创建一个Qt Console Application程序Demo_2_2_Functions。项目创建完成后,打开main.cpp,修改代码如下:

#include <QCoreApplication>
#include <QDebug>// --- 函数定义 ---
// 这个函数接收一个double类型的参数(parameter),没有返回值(void)
// 它的作用是封装了完整的尺寸检查逻辑
void checkScrewDiameter(double diameterToTest)
{qDebug() << "--- 开始检查直径:" << diameterToTest << "mm ---";const double standardDiameter = 5.0;const double tolerance = 0.05;if (diameterToTest > standardDiameter + tolerance) {qDebug() << "判定结果: 不合格,直径过大。";} else if (diameterToTest < standardDiameter - tolerance) {qDebug() << "判定结果: 不合格,直径过小。";} else {qDebug() << "判定结果: 合格,尺寸在公差范围内。";}qDebug() << "--- 检查结束 ---" << Qt::endl; // Qt::endl显式地换行
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// --- 函数调用 ---// 通过函数名和传递相应的参数来执行函数中的代码checkScrewDiameter(5.08); // 调用函数,检查一个过大的螺丝checkScrewDiameter(4.93); // 调用函数,检查一个过小的螺丝checkScrewDiameter(5.01); // 调用函数,检查一个合格的螺丝return a.exec();
}

单击 Qt Creator 左下角的绿色“运行”按钮,可以看到如下结果:

--- 开始检查直径: 5.08 mm ---
判定结果: 不合格,直径过大。      
--- 检查结束 ------ 开始检查直径: 4.93 mm ---     
判定结果: 不合格,直径过小。      
--- 检查结束 ------ 开始检查直径: 5.01 mm ---     
判定结果: 合格,尺寸在公差范围内。
--- 检查结束 ---

关键代码分析:
(1) 函数定义: “返回值类型 函数名(参数类型1 参数名1, ...)”是定义函数的基本形式。void是一种特殊的返回类型,表示该函数执行完毕后不返回任何值。
(2) 函数参数: double diameterToTest是函数的形式参数(形参),它是在函数定义时声明的,作为函数内部的一个局部变量来接收外部传入的数据。
(3) 函数调用: checkScrewDiameter(5.08)是在main函数中调用已定义的函数。5.08是实际参数(实参),在调用发生时,它的值会被复制一份并传递给函数中的形参diameterToTest
(4) const关键字: const double standardDiameter = 5.0; const表示standardDiameter是一个常量,其值在程序运行期间不能被修改。对于程序中固定不变的数值(如标准、公差),使用常量是一种推荐的编程实践,可以防止意外修改并提高代码的可读性。

2.3 循环与容器:批量处理

【例2-3】 批量质检一批产品。

循环是一种控制结构,它允许一段代码根据设定的条件重复执行多次。容器则是一种特殊的对象,专门用于存储和管理一组数据集合。当需要对一个集合中的所有元素执行相同操作时(例如,检查流水线上的一整批产品),将循环与容器结合使用,可以实现高效的自动化处理。

使用 Qt Creator 创建一个Qt Console Application程序Demo_2_3_LoopsAndContainers。项目创建完成后,打开main.cpp,修改代码如下:

#include <QCoreApplication>
#include <QDebug>
#include <QVector> // 包含QVector容器的头文件int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 创建一个QVector容器,用于存放一批待检测的螺丝直径QVector<double> diameterBatch;diameterBatch.append(5.01); // 使用append()方法向容器末尾添加元素diameterBatch.append(4.98);diameterBatch.append(5.09); // 这个不合格diameterBatch.append(4.92); // 这个也不合格diameterBatch.append(5.04);qDebug() << "流水线来了一批产品,共" << diameterBatch.size() << "个,开始质检...";int qualifiedCount = 0;// 使用for循环遍历QVector中的每一个元素for (int i = 0; i < diameterBatch.size(); ++i) {double currentDiameter = diameterBatch[i]; // 使用索引[i]访问容器中的元素bool isCurrentQualified = (currentDiameter >= 4.95 && currentDiameter <= 5.05);if (isCurrentQualified) {qDebug() << "第" << i + 1 << "个螺丝,直径" << currentDiameter << "mm, 合格。";qualifiedCount++;} else {qDebug() << "第" << i + 1 << "个螺丝,直径" << currentDiameter << "mm, 不合格!";}}qDebug() << "质检完成。合格数量:" << qualifiedCount;return a.exec();
}

单击 Qt Creator 左下角的绿色“运行”按钮,可以看到如下结果:

流水线来了一批产品,共 5 个,开始质检...
第 1 个螺丝,直径 5.01 mm, 合格。  
第 2 个螺丝,直径 4.98 mm, 合格。  
第 3 个螺丝,直径 5.09 mm, 不合格!
第 4 个螺丝,直径 4.92 mm, 不合格!
第 5 个螺丝,直径 5.04 mm, 合格。  
质检完成。合格数量: 3

关键代码分析:
(1) #include <QVector>: QVector是Qt提供的一个模板容器类,功能类似于一个可以动态调整大小的数组。要使用它,必须包含此头文件。
(2) QVector<double>: 定义了一个专门用于存放double类型数据的QVector容器。尖括号< >中的类型指定了容器内所有元素的类型。
(3) append(): 这是QVector的成员函数,用于在容器的末尾追加一个新元素。
(4) size(): 这是QVector的成员函数,用于获取容器中当前存储的元素总数。
(5) for循环结构: for(int i = 0; i < diameterBatch.size(); ++i)是最经典的for循环结构。它包含三个部分,由分号隔开:

  • 初始化: int i = 0,创建一个循环计数器i并赋初值为0。
  • 循环条件: i < diameterBatch.size(),每次循环开始前检查此条件,若为真则执行循环体,否则退出循环。
  • 迭代表达式: ++i,每次循环体执行完毕后执行此操作,使计数器加1。
    (6) 元素访问: diameterBatch[i],通过方括号和索引i(从0开始)来访问QVector容器中的具体元素。
    (7) &&运算符: (currentDiameter >= 4.95 && currentDiameter <= 5.05)中的&&是逻辑“与”运算符,它表示其两侧的条件必须同时为真,整个表达式的结果才为真。

三、面向对象编程:封装数据与行为

当程序逻辑变得复杂时,使用零散的变量和函数来管理会变得混乱。面向对象编程(Object-Oriented Programming, OOP)提供了一种更高级的组织方式,其核心就是类(Class)

【核心概念:数据与行为的统一体】

是创建对象的“蓝图”。它将描述某个事物的数据(称为属性或成员变量)和能对这些数据进行的操作(称为方法或成员函数)封装(Encapsulation)在一起。通过类,可以创建出具体的对象(Object),每个对象都是一个独立、完整的实体,极大地提高了代码的结构化程度。

【例2-4】 创建一个螺丝计数器类。

1. 创建项目与类文件

  • 新建一个名为 Demo_2_4_Classes 的Qt控制台项目。
  • 在Qt Creator中,右键点击项目名称,选择添加新文件... -> C++ -> C++ Class,类名输入 SimpleCounter,基类保持默认的 ,完成向导。Qt Creator会自动创建simplecounter.hsimplecounter.cpp

2. 编写代码 (simplecounter.h)

#ifndef SIMPLECOUNTER_H
#define SIMPLECOUNTER_H// 类的声明
class SimpleCounter
{
public:// 构造函数:在创建对象时自动调用,用于初始化SimpleCounter();// 公有(public)成员函数: 外部代码可以直接调用void increment();       // 计数加一void clear();           // 计数清零int getCount() const;   // 获取当前计数值private:// 私有(private)成员变量: 外部代码无法直接访问,实现了封装和保护int m_count;
};#endif // SIMPLECOUNTER_H

3. 编写代码 (simplecounter.cpp)

#include "simplecounter.h"// 构造函数的实现
SimpleCounter::SimpleCounter()
{// 在这里进行初始化工作m_count = 0;
}// 成员函数的实现
void SimpleCounter::increment()
{m_count++;
}void SimpleCounter::clear()
{m_count = 0;
}// const关键字表示这个函数不会修改类的任何成员变量
int SimpleCounter::getCount() const
{return m_count;
}

4. 编写代码 (main.cpp)

#include <QCoreApplication>
#include <QDebug>
#include "simplecounter.h" // 包含我们自己定义的类的头文件int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug() << "创建两个计数器: 合格品计数器和次品计数器";// 从SimpleCounter类创建两个具体的对象SimpleCounter qualifiedCounter;SimpleCounter defectiveCounter;// 模拟生产过程qDebug() << "生产了3个合格品...";qualifiedCounter.increment();qualifiedCounter.increment();qualifiedCounter.increment();qDebug() << "生产了1个次品...";defectiveCounter.increment();// 通过公有方法获取内部的计数值并打印qDebug() << "当前合格品数量:" << qualifiedCounter.getCount();qDebug() << "当前次品数量:" << defectiveCounter.getCount();return a.exec();
}

5. 运行结果

创建两个计数器: 合格品计数器和次品计数器
生产了3个合格品...
生产了1个次品...  
当前合格品数量: 3 
当前次品数量: 1

关键代码分析:
(1) 头文件(.h)与源文件(.cpp): 在C++中,类的声明(它有什么)通常放在头文件中,而成员函数的具体实现(它怎么做)放在源文件中。这是一种代码组织规范。
(2) public:private:: 这是访问说明符。public部分是类的对外接口,任何代码都可以访问。private部分是类的内部实现,只有该类的成员函数才能访问,外部代码无法直接触及。这体现了封装的思想,保护了内部数据的安全性。
(3) 构造函数: SimpleCounter()是一个特殊的成员函数,它没有返回类型,且函数名与类名完全相同。在创建类的对象时(如SimpleCounter qualifiedCounter;),构造函数会被自动调用,是执行初始化操作的最佳位置。
(4) SimpleCounter::: ::是作用域解析运算符。在.cpp文件中,它用于指明一个函数实现是属于哪个类的。

四、Qt的核心扩展:信号与槽通信

【核心概念:Qt的灵魂机制】

在图形界面程序中,一个对象的状态改变(如按钮被点击)常常需要通知其他多个对象。如果使用直接函数调用的方式,对象之间会产生紧密的依赖关系(耦合),不利于程序的维护和扩展。

为此,Qt引入了其最核心、最强大的创新之一:信号与槽(Signals and Slots)

  • 信号(Signal): 当对象内部状态发生改变时,由该对象发射(emit)出去的一种“广播”或“通知”。它只负责发出通知,不关心谁会收到。
  • 槽(Slot): 一个普通的成员函数,用于接收并处理某个信号。

通过connect函数,可以将一个对象的信号与另一个(或同一个)对象的槽连接起来。当信号被发射时,所有与之连接的槽函数就会被自动调用。这种机制使得信号的发送方和接收方可以互不知道对方的存在,实现了完美的解耦。

要让一个类支持信号与槽,必须:

  1. 公有继承自 QObject
  2. 在类声明的私有区顶部添加 Q_OBJECT 宏。

【例2-5】 工作者完成任务后通知管理者。

1. 创建项目与类文件

  • 新建一个名为 Demo_2_5_SignalsAndSlots 的Qt控制台项目。
  • 分别添加 WorkerManager 两个C++类,注意它们的基类都要选择 QObject

2. 编写代码 (worker.h & worker.cpp)

// worker.h
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QString>class Worker : public QObject
{Q_OBJECT // 必须添加此宏以支持信号与槽
public:explicit Worker(QObject *parent = nullptr);void doWork(); // 模拟执行一个任务
signals:// 信号只需要声明,无需实现。在signals关键字下声明void workFinished(const QString &result);
};
#endif // WORKER_H// worker.cpp
#include "worker.h"
#include <QDebug>
#include <QThread>Worker::Worker(QObject *parent) : QObject(parent) {}
void Worker::doWork()
{qDebug() << "[工作者] 开始执行耗时任务...";QThread::sleep(2); // 模拟耗时2秒QString result = "所有螺丝检测完毕";qDebug() << "[工作者] 任务完成,准备发射信号...";emit workFinished(result); // 使用emit关键字发射信号
}

3. 编写代码 (manager.h & manager.cpp)

// manager.h
#ifndef MANAGER_H
#define MANAGER_H
#include <QObject>
#include <QString>class Manager : public QObject
{Q_OBJECT
public:explicit Manager(QObject *parent = nullptr);
public slots:// 槽函数声明在 public slots: 区域void onWorkFinished(const QString &result);
};
#endif // MANAGER_H// manager.cpp
#include "manager.h"
#include <QDebug>Manager::Manager(QObject *parent) : QObject(parent) {}void Manager::onWorkFinished(const QString &result)
{qDebug() << "[管理者] 收到信号,槽函数被调用!";qDebug() << "  > 结果:" << result;
}

4. 编写代码 (main.cpp)

#include <QCoreApplication>
#include "worker.h"
#include "manager.h"
#include <QDebug>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);Worker worker;Manager manager;// --- 信号与槽的连接 ---QObject::connect(&worker, &Worker::workFinished,&manager, &Manager::onWorkFinished);qDebug() << "[主程序] 命令工作者开始工作。";worker.doWork(); // 调用此函数将最终导致信号被发射return a.exec();
}

5. 运行结果

[主程序] 命令工作者开始工作。
[工作者] 开始执行耗时任务...
[工作者] 任务完成,准备发射信号...
[管理者] 收到信号,槽函数被调用!> 结果: "所有螺丝检测完毕"

关键代码分析:
(1) QObjectQ_OBJECT: WorkerManager都继承自QObject,并在类声明中包含了Q_OBJECT宏,这是使用信号槽的前提。Qt的MOC(元对象编译器)会预处理这个宏,生成支持信号槽所需的额外代码。
(2) signals:: 用于声明信号函数。信号函数没有函数体,其返回值类型通常是void
(3) emit: 这是一个空宏,在代码中用于标记一个信号的发射。当执行到emit workFinished(...)时,Qt的元对象系统会接管,并调用所有与workFinished信号连接的槽。
(4) public slots:: 用于声明槽函数。槽函数的本质是一个普通的成员函数,可以有自己的参数和实现。
(5) QObject::connect(...): 这是建立连接的核心函数。其最常用的形式是:
connect(信号发送者地址, &发送者类::信号名, 信号接收者地址, &接收者类::槽函数名);
这种写法在编译时就会进行类型检查,如果信号和槽的参数不匹配,或者函数名写错,编译器会直接报错,非常安全。

五、总结与展望

在本篇文章中,我们不仅复习了C++的基础语法,更深入探讨了面向对象编程的核心——类与对象,以及Qt框架的灵魂——信号与槽机制。这些是构建任何复杂、可维护的Qt应用程序都不可或缺的知识。

现在,我们已经具备了用C++构建结构化、可交互的后端逻辑的能力。在下一篇文章**【《使用Qt Quick从零构建AI螺丝瑕疵检测系统》——3. QML入门:像搭积木一样构建UI】**中,我们将把目光转向用户界面,开始探索QML的精彩世界,学习如何为我们的C++后端打造一个现代化的“面孔”。

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

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

相关文章

Navicat 远程连接SQLlite数据库

1、SQLlite数据库是一个本地.db文件&#xff0c;默认不支持远程连接&#xff1b; 2、Navicat 可以通过ntunnel_sqlite.php文件连接远程SQLlite库&#xff1b; 3、安装Navicat&#xff0c;安装完成&#xff0c;在安装目录下找到ntunnel_sqlite.php文件&#xff1b; 4、上传当前文…

OpenCV用于计算光流的一个类cv::optflow::DualTVL1OpticalFlow

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::optflow::DualTVL1OpticalFlow 是 OpenCV 中用于计算光流的一个类&#xff0c;特别地&#xff0c;它实现了基于双帧 TV-L1&#xff08;Total V…

PyQt5在Pycharm上的环境搭建 -- Qt Designer + Pyuic + Pyrcc组合,大幅提升GUI开发效率

软件安装 目标软件&#xff1a; Python解释器Pycharm编辑器 Python官网&#xff1a; 点击访问Python官网 Pycharm官网&#xff1a;点击访问Pycharm官网 环境搭建 搭建完成后最终的环境详情&#xff1a; python安装路径&#xff1a;D:\ProgramEnviron\Python\Python311Pyth…

30天打牢数模基础-卷积神经网络讲解

案例代码实现一、代码说明本案例使用PyTorch实现一个改进版LeNet-5模型&#xff0c;用于CIFAR-10数据集的图像分类任务。代码包含以下核心步骤&#xff1a;数据加载与预处理&#xff08;含数据增强&#xff0c;划分训练/验证/测试集&#xff09;&#xff1b;定义CNN网络结构&am…

Dev-C++——winAPI贪吃蛇小游戏

&#x1f680;欢迎互三&#x1f449;&#xff1a;雾狩 &#x1f48e;&#x1f48e; &#x1f680;关注博主&#xff0c;后期持续更新系列文章 &#x1f680;如果有错误感谢请大家批评指出&#xff0c;及时修改 &#x1f680;感谢大家点赞&#x1f44d;收藏⭐评论✍ 今天水一篇吧…

【openbmc6】entity-manager

文章目录 2.1 事件监听:dbus在linux上使用的底层通信方式多半是unix domain socket ,事件的到来可被抽象为:socket上有数据,可读 2.2 事件处理:由于主线程肯定有逻辑得跑,因此新开一个线程甚至多个线程专门用来监听和处理事件,但存在多线程就意味着可能存在竞争,存在竞…

Java 实现 UDP 多发多收通信

在网络通信领域&#xff0c;UDP&#xff08;用户数据报协议&#xff09;以其无连接、高效率的特点&#xff0c;在实时通信场景中占据重要地位。本文将结合一段实现 UDP 多发多收的 Java 代码&#xff0c;详细解析其实现逻辑&#xff0c;帮助开发者深入理解 UDP 通信的底层逻辑与…

Java学习第六十二部分——Git

目录 一、关键概述 二、核心概念 三、常用命令 四、优势因素 五、应用方案 六、使用建议 一、关键概述 提问&#xff1a;Git 是什么&#xff1f; 回答&#xff1a;一句话&#xff0c;分布式版本控制系统&#xff08;DVCS&#xff09;&#xff0c;用来跟踪文件&#…

CDN和DNS 在分布式系统中的作用

一、DNS&#xff1a;域名系统&#xff08;Domain Name System&#xff09; 1. 核心功能 DNS是互联网的“地址簿”&#xff0c;负责将人类易记的域名&#xff08;如www.baidu.com&#xff09;解析为计算机可识别的IP地址&#xff08;如180.101.50.242&#xff09;。没有DNS&…

uniapp用webview导入本地网页,ios端打开页面空白问题

目前还没解决&#xff0c;DCloud官方也说不行 IOS下webview加载本地网页时&#xff0c;无法加载资源 - DCloud问答

软考 系统架构设计师系列知识点之面向服务架构设计理论与实践(8)

接前一篇文章:软考 系统架构设计师系列知识点之面向服务架构设计理论与实践(7) 所属章节: 第15章. 面向服务架构设计理论与实践 第3节 SOA的参考架构 15.3 SOA的参考架构 IBM的Websphere业务集成参考架构(如图15-2所示,以下简称参考架构)是典型的以服务为中心的企业集…

基于 Docker 及 Kubernetes 部署 vLLM:开启机器学习模型服务的新篇章

在当今数字化浪潮中&#xff0c;机器学习模型的高效部署与管理成为众多开发者和企业关注的焦点。vLLM 作为一款性能卓越的大型语言模型推理引擎&#xff0c;其在 Docker 及 Kubernetes 上的部署方式如何呢&#xff1f;本文将深入探讨如何在 Docker 及 Kubernetes 集群中部署 vL…

工业互联网六大安全挑战的密码“解法”

目录 工业互联网密码技术应用Q&A Q1&#xff1a;设备身份认证与接入控制 Q2&#xff1a;通信数据加密与完整性保护 Q3&#xff1a;远程安全访问 Q4&#xff1a;平台与数据安全 Q5&#xff1a;软件与固件安全 Q6&#xff1a;日志审计与抗抵赖 首传信安-解决方案 总…

基于springboot的在线问卷调查系统的设计与实现(源码+论文)

一、开发环境 1 Java语言 Java语言是当今为止依然在编程语言行业具有生命力的常青树之一。Java语言最原始的诞生&#xff0c;不仅仅是创造者感觉C语言在编程上面很麻烦&#xff0c;如果只是专注于业务逻辑的处理&#xff0c;会导致忽略了各种指针以及垃圾回收这些操作&#x…

民法学学习笔记(个人向) Part.1

民法学学习笔记(个人向) Part.1有关民法条文背后的事理、人心、经济社会基础&#xff1b;民法的结构民法学习的特色就是先学最难的民法总论&#xff0c;再学较难的物权法、合同法等&#xff0c;最后再学习最简单的婚姻、继承、侵权部分。这是一个由难到易的过程&#xff0c;尤为…

ElasticSearch Doc Values和Fielddata详解

一、Doc Values介绍倒排索引在搜索包含指定 term 的文档时效率极高&#xff0c;但在执行相反操作&#xff0c;比如查询一个文档中包含哪些 term&#xff0c;以及进行排序、聚合等与指定字段相关的操作时&#xff0c;表现就很差了&#xff0c;这时候就需要用到 Doc Values。倒排…

【C语言】解决VScode中文乱码问题

文章目录【C语言】解决VScode中文乱码问题弹出无法写入用户设置的处理方法弹出无法在只读编辑器编辑的问题处理方法【C语言】解决VScode中文乱码问题 &#x1f4ac;欢迎交流&#xff1a;在学习过程中如果你有任何疑问或想法&#xff0c;欢迎在评论区留言&#xff0c;我们可以共…

MySQL笔记4

一、范式1.概念与意义范式&#xff08;Normal Form&#xff09;是数据库设计需遵循的规范&#xff0c;解决“设计随意导致后期重构困难”问题。主流有 三大范式&#xff08;1NF、2NF、3NF&#xff09;&#xff0c;还有进阶的 BCNF、4NF、5NF 等&#xff0c;范式间是递进依赖&am…

切比雪夫不等式的理解以及推导【超详细笔记】

文章目录参考教程一、意义1. 正态分布的 3σ 法则2. 不等式的含义3. 不等式的意义二、不等式的证明1. 马尔科夫不等式马尔可夫不等式证明(YYY 为非负随机变量 &#xff09;2. 切比雪夫不等式推导参考教程 一个视频&#xff0c;彻底理解切比雪夫不等式 一、意义 1. 正态分布的…

Spring Boot Jackson 序列化常用配置详解

一、引言在当今的 Web 开发领域&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;已然成为数据交换的中流砥柱。无论是前后端分离架构下前后端之间的数据交互&#xff0c;还是微服务架构里各个微服务之间的通信&#xff0c;JSON 都承担着至关重要的角色 。它…