[C++] --- 常用设计模式

策略模式

迭代器模式

适配器模式

工厂模式

超级工厂模式

享元模式

代理模式

模板方法模式

0 设计模式的SOLID原则

SOLID是一个缩写词,代表以下设计原则(及其缩写):

复制代码
    Single Responsibility Principle (SRP)
    Open-Closed Principle (OCP)
    Liskov Substitution Principle (LSP)
    Interface Segregation Principle (ISP)
    Dependency Inversion Principle (DIP)

这五个特定的主题贯穿了对模式和软件设计的一般讨论,所以在我们深入研究设计模式之前(我知道你们都很渴望),我们将简要回顾一下SOLID原则是什么。

0.1 Single Responsibility Principle (SRP): 单一职责原则

一个类或者一个模块只做一件事。让一个类或者一个模块专注于单一的功能,减少功能之间的耦合程度。这样做在需要修改某个功能时,就不会影响到其他的功能。

0.2 Open Closed Principle(OCP):开闭原则

对扩展开放,对修改关闭。一个类独立之后就不应该去修改它,而是以扩展的方式适应新需求。

0.3 Liskov Substitution Principle(LSP):里氏替换原则

所有基类出现的地方都可以用派生类替换而不会让程序产生错误,派生类可以扩展基类的功能,但不能改变基类原有的功能。

0.4 Interface Segregation Principle(ISP):接口隔离原则

一个接口应该拥有尽可能少的行为,使其精简单一。对于不同的功能的模块分别使用不同接口,而不是使用同一个通用的接口。

0.5 Dependence Inversion Principle(DIP):依赖倒置原则

高级模块不应该依赖低级模块,而是依赖抽象接口,通过抽象接口使用对应的低级模块。

1 策略模式

策略模式(Strategy Pattern)是一种行为型设计模式,其核心思想是将算法家族封装起来,让它们之间可以互相替换,从而使算法的变化独立于使用算法的客户端。这种模式特别适合处理 "同一问题存在多种解决方案,且需要动态选择其中一种" 的场景。

策略模式包含三个关键角色:

  • 环境类(Context):持有策略对象的引用,负责调用具体策略
  • 抽象策略接口(Strategy):定义所有具体策略的公共接口
  • 具体策略类(ConcreteStrategy):实现抽象策略接口,包含具体算法

适用场景

  • 一个问题有多种解决方案,需要动态选择其中一种
  • 算法需要被复用或替换
  • 避免使用多重条件判断语句

代码示例:

复制代码
#include <iostream>
#include <string>
#include <memory>
#include <chrono>
#include <cstdint>

// 信号数据结构
struct SignalData {
    uint32_t id;             // 信号ID
    uint64_t timestamp;      // 时间戳
    std::string raw_data;    // 原始数据
    bool current_state;      // 当前状态
    bool previous_state;     // 上一次状态
};

// 故障信息结构
struct FaultInfo {
    uint32_t signal_id;
    std::string fault_type;
    uint64_t timestamp;
};

// --------------------------
// 1. 抽象策略接口:信号处理策略
// --------------------------
class SignalProcessingStrategy {
public:
    virtual ~SignalProcessingStrategy() = default;
    
    // 判断信号状态是否改变
    virtual bool isStateChanged(const SignalData& signal) = 0;
    
    // 检查信号是否有故障
    virtual bool hasFault(const SignalData& signal) = 0;
    
    // 获取故障信息
    virtual FaultInfo getFaultInfo(const SignalData& signal) = 0;
    
    // 获取策略名称
    virtual std::string getStrategyName() const = 0;
};

// --------------------------
// 2. 具体策略实现
// --------------------------

// 高频信号处理策略
class HighFrequencyStrategy : public SignalProcessingStrategy {
public:
    bool isStateChanged(const SignalData& signal) override {
        // 高频信号状态变化判断:阈值更敏感
        return signal.current_state != signal.previous_state;
    }
    
    bool hasFault(const SignalData& signal) override {
        // 高频信号故障判断:检查是否连续3次状态异常
        static std::unordered_map<uint32_t, int> fault_counter;
        if (signal.current_state == false) {  // 假设false表示异常
            fault_counter[signal.id]++;
            return fault_counter[signal.id] >= 3;
        } else {
            fault_counter[signal.id] = 0;
            return false;
        }
    }
    
    FaultInfo getFaultInfo(const SignalData& signal) override {
        return {
            signal.id,
            "高频信号连续异常",
            signal.timestamp
        };
    }
    
    std::string getStrategyName() const override {
        return "高频信号处理策略";
    }
};

// 低频信号处理策略
class LowFrequencyStrategy : public SignalProcessingStrategy {
public:
    bool isStateChanged(const SignalData& signal) override {
        // 低频信号状态变化判断:需连续2次确认
        static std::unordered_map<uint32_t, bool> last_check;
        bool result = (last_check[signal.id] == signal.current_state) && 
                      (signal.current_state != signal.previous_state);
        last_check[signal.id] = signal.current_state;
        return result;
    }
    
    bool hasFault(const SignalData& signal) override {
        // 低频信号故障判断:检查超时(500ms未更新)
        auto now = std::chrono::duration_cast<std::chrono::milliseconds>
                  (std::chrono::system_clock::now().time_since_epoch()).count();
        return (now - signal.timestamp) > 500;
    }
    
    FaultInfo getFaultInfo(const SignalData& signal) override {
        return {
            signal.id,
            "低频信号超时未更新",
            signal.timestamp
        };
    }
    
    std::string getStrategyName() const override {
        return "低频信号处理策略";
    }
};

// E2E信号处理策略
class E2EStrategy : public SignalProcessingStrategy {
public:
    bool isStateChanged(const SignalData& signal) override {
        // E2E信号状态变化判断:检查校验和
        uint8_t checksum = calculateChecksum(signal.raw_data);
        return checksum != signal.raw_data.back();  // 假设最后一个字节是校验和
    }
    
    bool hasFault(const SignalData& signal) override {
        // E2E信号故障判断:校验和错误或计数器异常
        return isStateChanged(signal) || checkCounter(signal);
    }
    
    FaultInfo getFaultInfo(const SignalData& signal) override {
        if (isStateChanged(signal)) {
            return {signal.id, "E2E信号校验和错误", signal.timestamp};
        } else {
            return {signal.id, "E2E信号计数器异常", signal.timestamp};
        }
    }
    
    std::string getStrategyName() const override {
        return "E2E信号处理策略";
    }
    
private:
    // 计算校验和(简单实现)
    uint8_t calculateChecksum(const std::string& data) {
        uint8_t sum = 0;
        for (size_t i = 0; i < data.size() - 1; ++i) {  // 排除最后一个字节
            sum += static_cast<uint8_t>(data[i]);
        }
        return sum;
    }
    
    // 检查计数器(简单实现)
    bool checkCounter(const SignalData& signal) {
        static std::unordered_map<uint32_t, uint8_t> last_counter;
        uint8_t current_counter = static_cast<uint8_t>(signal.raw_data[0]);
        bool result = (current_counter - last_counter[signal.id]) % 256 != 1;
        last_counter[signal.id] = current_counter;
        return result;
    }
};

// --------------------------
// 3. 环境类:信号处理器
// --------------------------
class SignalProcessor {
private:
    std::unique_ptr<SignalProcessingStrategy> strategy_;
    
    // 上传故障信息到系统
    void uploadFault(const FaultInfo& fault) {
        std::cout << "\n=== 上传故障信息 ===" << std::endl;
        std::cout << "信号ID: " << fault.signal_id << std::endl;
        std::cout << "故障类型: " << fault.fault_type << std::endl;
        std::cout << "时间戳: " << fault.timestamp << std::endl;
        std::cout << "===================\n" << std::endl;
    }

public:
    // 构造函数:指定初始策略
    explicit SignalProcessor(std::unique_ptr<SignalProcessingStrategy> strategy)
        : strategy_(std::move(strategy)) {}
    
    // 切换策略
    void setStrategy(std::unique_ptr<SignalProcessingStrategy> strategy) {
        if (strategy) {
            std::cout << "\n切换信号处理策略: " << strategy_->getStrategyName() 
                      << " -> " << strategy->getStrategyName() << std::endl;
            strategy_ = std::move(strategy);
        }
    }
    
    // 处理信号的主流程
    void processSignal(SignalData& signal) {
        std::cout << "\n----- 处理信号 (ID: " << signal.id << ") -----" << std::endl;
        std::cout << "使用策略: " << strategy_->getStrategyName() << std::endl;
        
        // 检查状态是否改变
        if (strategy_->isStateChanged(signal)) {
            std::cout << "信号状态发生改变" << std::endl;
            // 更新上一次状态
            signal.previous_state = signal.current_state;
        } else {
            std::cout << "信号状态未改变" << std::endl;
        }
        
        // 检查是否有故障
        if (strategy_->hasFault(signal)) {
            std::cout << "检测到信号故障!" << std::endl;
            // 上传故障信息
            FaultInfo fault = strategy_->getFaultInfo(signal);
            uploadFault(fault);
        } else {
            std::cout << "信号正常" << std::endl;
        }
    }
};

// --------------------------
// 4. 客户端代码
// --------------------------
int main() {
    // 创建信号处理器,初始使用高频信号策略
    auto processor = std::make_unique<SignalProcessor>(
        std::make_unique<HighFrequencyStrategy>()
    );
    
    // 处理高频信号
    SignalData high_freq_signal{
        0x101,  // ID
        1620000000001,  // 时间戳
        "",  // 原始数据
        true,  // 当前状态
        false  // 上一次状态
    };
    processor->processSignal(high_freq_signal);
    
    // 再次处理高频信号(模拟连续异常)
    high_freq_signal.current_state = false;
    high_freq_signal.timestamp = 1620000000002;
    processor->processSignal(high_freq_signal);
    
    high_freq_signal.timestamp = 1620000000003;
    processor->processSignal(high_freq_signal);
    
    high_freq_signal.timestamp = 1620000000004;
    processor->processSignal(high_freq_signal);  // 第三次异常,触发故障
    
    // 切换到低频信号策略
    processor->setStrategy(std::make_unique<LowFrequencyStrategy>());
    
    // 处理低频信号
    SignalData low_freq_signal{
        0x201,  // ID
        1620000000005,  // 时间戳
        "",  // 原始数据
        true,  // 当前状态
        true   // 上一次状态
    };
    processor->processSignal(low_freq_signal);
    
    // 处理超时的低频信号
    low_freq_signal.timestamp = 1620000000000;  // 过期的时间戳
    processor->processSignal(low_freq_signal);  // 触发超时故障
    
    // 切换到E2E信号策略
    processor->setStrategy(std::make_unique<E2EStrategy>());
    
    // 处理E2E信号(校验和正确)
    SignalData e2e_signal{
        0x301,  // ID
        1620000000006,  // 时间戳
        "E2E_OK\x05",  // 原始数据,最后一个字节是校验和
        true,   // 当前状态
        true    // 上一次状态
    };
    processor->processSignal(e2e_signal);
    
    // 处理有问题的E2E信号(校验和错误)
    e2e_signal.raw_data = "E2E_BAD\x00";  // 错误的校验和
    e2e_signal.timestamp = 1620000000007;
    processor->processSignal(e2e_signal);  // 触发校验和故障
    
    return 0;
}

代码解析,

复制代码
    抽象策略接口(SignalProcessingStrategy)
        定义了所有信号处理策略的统一接口,包括状态变化判断、故障检测、故障信息获取等方法
        所有具体信号类型的处理策略都必须实现这些接口
    具体策略实现
        高频信号策略(HighFrequencyStrategy):对状态变化敏感,连续 3 次异常即判定为故障
        低频信号策略(LowFrequencyStrategy):状态变化需要连续确认,超时未更新判定为故障
        E2E 信号策略(E2EStrategy):基于校验和和计数器判断状态和故障
    环境类(SignalProcessor)
        持有一个策略接口的引用,封装了信号处理的主流程
        提供切换策略的方法,使得可以动态改变信号处理方式
        负责调用策略的方法进行状态判断和故障处理,并统一处理故障上传

2 适配器模式

适配器模式(Adapter Pattern)是一种结构型设计模式,其核心是将一个类的接口转换成客户端期望的另一种接口,使原本因接口不兼容而无法协作的类能够一起工作。在智能驾驶开发中,由于传感器、算法、硬件的多样性,适配器模式被广泛用于解决接口适配问题。

核心解决的问题

  • 接口兼容性:当新组件(如第三方算法、新型传感器)的接口与现有系统不一致时,无需修改原有代码即可使其兼容。
  • 复用性扩展:复用已有功能组件(如开源算法),通过适配使其融入现有架构,避免重复开发。
  • 系统稳定性:隔离外部组件的接口变化,原有系统代码无需修改,降低维护成本。

核心角色

  • 目标接口(Target):客户端期望的统一接口,定义了系统需要的功能规范。
  • 适配者(Adaptee):需要被适配的现有类或接口(如第三方算法、硬件驱动),其接口与目标接口不兼容。
  • 适配器(Adapter):实现目标接口,内部持有适配者的引用,将目标接口的调用转换为对适配者的调用。

两种实现方式

  • 类适配器:通过多重继承(继承目标接口和适配者)实现适配(C++ 支持,但因多重继承复杂性较少使用)。
  • 对象适配器:通过组合(持有适配者对象)实现适配,更灵活,是主流实现方式。

代码示例:

复制代码
#include <iostream>
#include <vector>
#include <string>
#include <memory>

// ------------------------------
// 1. 目标接口(Target):系统期望的统一检测接口
// ------------------------------
struct DetectionResult {
    std::string class_name;  // 目标类别(如"car"、"pedestrian")
    float x;                 // 检测框x坐标
    float y;                 // 检测框y坐标
    float width;             // 检测框宽度
    float height;            // 检测框高度
    float confidence;        // 置信度
};

// 目标接口:统一的目标检测器接口
class TargetDetector {
public:
    virtual ~TargetDetector() = default;
    // 初始化检测器(返回是否成功)
    virtual bool init(const std::string& model_path) = 0;
    // 检测接口(输入图像数据,输出检测结果)
    virtual std::vector<DetectionResult> detect(
        const unsigned char* image_data, 
        int width, 
        int height) = 0;
    // 获取算法名称
    virtual std::string getName() const = 0;
};

// ------------------------------
// 2. 适配者(Adaptee):需要被适配的第三方算法
// ------------------------------

// 适配者1:YOLO算法(接口与目标接口不兼容)
class YoloAlgorithm {
public:
    // YOLO的初始化接口(参数不同)
    bool loadModel(const std::string& model_path, int gpu_id) {
        std::cout << "YoloAlgorithm: 加载模型 " << model_path 
                  << " (GPU ID: " << gpu_id << ")\n";
        return true;  // 模拟成功加载
    }
    
    // YOLO的检测接口(输入输出格式不同)
    struct YoloResult {
        int class_id;    // 类别ID(而非名称)
        float bbox[4];   // [x1, y1, x2, y2](与目标接口的宽高格式不同)
        float score;     // 分数(对应置信度)
    };
    std::vector<YoloResult> runDetection(
        const unsigned char* img, 
        int w, 
        int h, 
        float threshold) {  // 多了阈值参数
        // 模拟检测结果
        return {
            {0, {100, 200, 300, 400}, 0.92},  // 假设class_id=0对应"car"
            {1, {50, 150, 150, 350}, 0.88}   // 假设class_id=1对应"pedestrian"
        };
    }
};

// 适配者2:Faster R-CNN算法(接口不同)
class FasterRCNNAlgorithm {
public:
    // Faster R-CNN的初始化接口(无GPU参数)
    void initialize(const std::string& model_file, const std::string& config_file) {
        std::cout << "FasterRCNNAlgorithm: 初始化模型 " << model_file 
                  << " (配置: " << config_file << ")\n";
    }
    
    // Faster R-CNN的检测接口(返回格式不同)
    std::vector<std::tuple<std::string, float, float, float, float, float>> detectObjects(
        const unsigned char* image, 
        int width, 
        int height) {
        // 模拟检测结果(格式:(类别名, x, y, w, h, 置信度))
        return {
            {"car", 120, 220, 180, 190, 0.90},
            {"cyclist", 80, 180, 60, 120, 0.85}
        };
    }
};

// ------------------------------
// 3. 适配器(Adapter):将适配者转换为目标接口
// ------------------------------

// 适配器1:YOLO算法适配器
class YoloAdapter : public TargetDetector {
private:
    YoloAlgorithm yolo_;  // 持有适配者对象
    int gpu_id_;          // YOLO特有的参数
    float threshold_;     // YOLO特有的参数

public:
    YoloAdapter(int gpu_id = 0, float threshold = 0.5f)
        : gpu_id_(gpu_id), threshold_(threshold) {}
    
    bool init(const std::string& model_path) override {
        // 适配初始化接口:将目标接口的参数转换为YOLO需要的参数
        return yolo_.loadModel(model_path, gpu_id_);
    }
    
    std::vector<DetectionResult> detect(
        const unsigned char* image_data, 
        int width, 
        int height) override {
        // 1. 调用YOLO的检测接口
        auto yolo_results = yolo_.runDetection(
            image_data, width, height, threshold_);
        
        // 2. 转换结果格式(YOLO格式 → 目标接口格式)
        std::vector<DetectionResult> results;
        for (const auto& yolo_res : yolo_results) {
            DetectionResult res;
            // 转换类别ID为类别名
            res.class_name = (yolo_res.class_id == 0) ? "car" : 
                            (yolo_res.class_id == 1) ? "pedestrian" : "unknown";
            // 转换边界框格式(x1,y1,x2,y2 → x,y,width,height)
            res.x = yolo_res.bbox[0];
            res.y = yolo_res.bbox[1];
            res.width = yolo_res.bbox[2] - yolo_res.bbox[0];
            res.height = yolo_res.bbox[3] - yolo_res.bbox[1];
            res.confidence = yolo_res.score;
            results.push_back(res);
        }
        return results;
    }
    
    std::string getName() const override {
        return "YOLO Detector (Adapted)";
    }
};

// 适配器2:Faster R-CNN算法适配器
class FasterRCNNAdapter : public TargetDetector {
private:
    FasterRCNNAlgorithm frcnn_;  // 持有适配者对象
    std::string config_file_;    // Faster R-CNN特有的配置文件

public:
    FasterRCNNAdapter(std::string config_file)
        : config_file_(std::move(config_file)) {}
    
    bool init(const std::string& model_path) override {
        // 适配初始化接口:Faster R-CNN需要模型文件和配置文件
        frcnn_.initialize(model_path, config_file_);
        return true;  // FasterRCNNAlgorithm的initialize无返回值,默认成功
    }
    
    std::vector<DetectionResult> detect(
        const unsigned char* image_data, 
        int width, 
        int height) override {
        // 1. 调用Faster R-CNN的检测接口
        auto frcnn_results = frcnn_.detectObjects(image_data, width, height);
        
        // 2. 转换结果格式(Faster R-CNN格式 → 目标接口格式)
        std::vector<DetectionResult> results;
        for (const auto& frcnn_res : frcnn_results) {
            DetectionResult res;
            res.class_name = std::get<0>(frcnn_res);
            res.x = std::get<1>(frcnn_res);
            res.y = std::get<2>(frcnn_res);
            res.width = std::get<3>(frcnn_res);
            res.height = std::get<4>(frcnn_res);
            res.confidence = std::get<5>(frcnn_res);
            results.push_back(res);
        }
        return results;
    }
    
    std::string getName() const override {
        return "Faster R-CNN Detector (Adapted)";
    }
};

// ------------------------------
// 客户端代码:智能驾驶感知系统
// ------------------------------
void runPerceptionSystem(TargetDetector& detector, const std::string& model_path) {
    // 初始化检测器(统一接口)
    if (!detector.init(model_path)) {
        std::cerr << "检测器初始化失败!\n";
        return;
    }
    
    std::cout << "\n运行检测器: " << detector.getName() << "\n";
    // 模拟输入图像数据(实际中是摄像头/激光雷达数据)
    unsigned char dummy_image[100 * 100] = {0};  // 占位图像数据
    // 执行检测(统一接口)
    auto results = detector.detect(dummy_image, 100, 100);
    
    // 输出检测结果
    std::cout << "检测到 " << results.size() << " 个目标:\n";
    for (const auto& res : results) {
        std::cout << "- " << res.class_name 
                  << " (置信度: " << res.confidence << "): "
                  << "位置(" << res.x << ", " << res.y << "), "
                  << "大小(" << res.width << "x" << res.height << ")\n";
    }
}

int main() {
    // 1. 使用YOLO适配器
    YoloAdapter yolo_adapter(0, 0.6f);  // 指定GPU ID和阈值
    runPerceptionSystem(yolo_adapter, "yolo_model.pt");
    
    // 2. 使用Faster R-CNN适配器
    FasterRCNNAdapter frcnn_adapter("frcnn_config.yaml");  // 指定配置文件
    runPerceptionSystem(frcnn_adapter, "frcnn_model.pth");
    
    return 0;
}

代码解析

在智能驾驶感知系统的示例中,适配器模式解决了 "多算法接口不统一" 的核心问题:

1 目标接口(TargetDetector):

定义了感知系统需要的统一接口(init初始化、detect检测),所有检测器必须遵循此规范,确保系统上层代码(如决策模块)能统一调用。

2 适配者(YoloAlgorithm、FasterRCNNAlgorithm):

代表第三方算法,它们的接口各不相同:

复制代码
    YOLO 需要loadModel(带 GPU ID)和runDetection(带阈值);
    Faster R-CNN 需要initialize(带配置文件)和detectObjects(返回格式不同)。

3 适配器(YoloAdapter、FasterRCNNAdapter):

实现TargetDetector接口,内部持有适配者对象,完成三项核心工作:

复制代码
    接口转换:将init调用转换为适配者的初始化方法(如loadModel);
    参数适配:补充适配者需要的额外参数(如 YOLO 的 GPU ID、Faster R-CNN 的配置文件);
    数据转换:将适配者返回的检测结果(如 YOLO 的bbox[x1,y1,x2,y2])转换为系统统一的DetectionResult格式。

4 客户端(runPerceptionSystem):

仅依赖TargetDetector接口,无需关心具体算法的实现细节,实现了 "算法替换不影响上层代码" 的灵活性(如切换 YOLO 和 Faster R-CNN 时,客户端代码无需修改)。

3 迭代器模式

4 享元模式

5 代理模式

6 模板方法模式

6.1 模板方法模式适用场景

  • 父类视角 : 一次性 实现 一个算法 不变的部分 , 并将 可变部分 留给 子类 实现 ;
  • 子类视角 : 各个子类中 , 公共部分 被提取出来 , 集中到一个公共的父类中 , 避免代码重复 ;

模板方法模式的目的是 让 子类可以扩展 或 具体实现固定方法的某个具体的步骤 ; 对于模板来说 , 是一套固定的算法 , 通过子类 可以扩展 固定算法中某些算法步骤 ;

6.2 模板方法模式优缺点

模板方法模式 将 不变的行为定义在父类中 , 去除子类的重复代码 , 体现其优势 , 提供了一个很好的代码复用平台 ;

模板方法模式缺点 :

  • 增加复杂性 : 类 数量增加 , 增加了系统复杂性 ; 引入了抽象类 , 对于每个实现 , 都需要定义一个子类 ;
  • 继承缺点 : 模板方法 主要 通过 继承实现 , 继承关系自身就有缺点 , 如果父类增加新的抽象方法 , 所有的子类都要修改一遍 ;

6.3 代码示例

复制代码
#include <iostream>
#include <memory>
#include <string>

// 抽象基类 - 定义算法骨架
class InferencePipeline {
public:
    virtual ~InferencePipeline() = default;
    
    // 模板方法 - 定义不变的流程
    void execute() {
        preProcess();  // 固定前处理
        inference();   // 平台相关的推理
        postProcess(); // 固定后处理
    }

protected:
    // 固定实现的前后处理
    void preProcess() {
        std::cout << "Common pre-processing: Data loading, normalization, etc." << std::endl;
    }
    
    void postProcess() {
        std::cout << "Common post-processing: Result formatting, output generation, etc." << std::endl;
    }
    
    // 平台特定的推理 - 由子类实现
    virtual void inference() = 0;
};

// Thor平台实现
class ThorInferencePipeline : public InferencePipeline {
protected:
    void inference() override {
        std::cout << "Thor platform inference: Optimized for Thor architecture" << std::endl;
        // Thor特定的推理代码
    }
};

// J6M平台实现
class J6MInferencePipeline : public InferencePipeline {
protected:
    void inference() override {
        std::cout << "J6M platform inference: Optimized for J6M architecture" << std::endl;
        // J6M特定的推理代码
    }
};

// 使用示例
int main() {
    std::cout << "=== Thor Platform ===" << std::endl;
    auto thorPipeline = std::make_unique<ThorInferencePipeline>();
    thorPipeline->execute();
    
    std::cout << "\n=== J6M Platform ===" << std::endl;
    auto j6mPipeline = std::make_unique<J6MInferencePipeline>();
    j6mPipeline->execute();
    
    return 0;
}

代码解析:

推理流程分为,前处理,推理,后处理,不同的平台,比喻thor和j6m,只有推理的代码不一样,前后处理的代码一样

相关推荐
Univin4 小时前
C++(10.4)
开发语言·数据结构·c++
YxVoyager4 小时前
Qt C++ :QLayout 布局管理
c++·qt
KyollBM4 小时前
每日羊题 (质数筛 + 数学 | 构造 + 位运算)
开发语言·c++·算法
Paul_09206 小时前
golang面经——map模块和sync.Map模块
开发语言
Univin6 小时前
C++(10.5)
开发语言·c++·算法
AA陈超6 小时前
虚幻引擎UE5专用服务器游戏开发-33 在上半身播放组合蒙太奇
c++·游戏·ue5·游戏引擎·虚幻
qq_428639616 小时前
虚幻基础:组件间的联动方式
c++·算法·虚幻
haogexiaole6 小时前
Java高并发常见架构、处理方式、api调优
java·开发语言·架构
张人玉7 小时前
C# 通讯关键类的API
开发语言·c#