news 2026/10/13 14:07:31

C++(C++17/20)最佳工厂写法和SLAM应用综合示例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++(C++17/20)最佳工厂写法和SLAM应用综合示例

现代 C++(C++17/20)下的最佳工厂写法


一、现代 C++ 工厂设计的基本原则

在 C++17/20 下,好的工厂写法通常满足:

  1. RAII + 明确所有权

    • 返回std::unique_ptr<T>为默认
  2. 无switch/ 无 RTTI

  3. 支持扩展而不修改(OCP)

  4. 构造逻辑与业务逻辑分离

  5. 尽量零运行期成本或可控成本


二、最推荐写法:注册式工厂(Registry-based Factory)

90% 工程项目的首选

1. 基本结构

classBase{public:virtual~Base()=default;virtualvoidrun()=0;};usingCreator=std::function<std::unique_ptr<Base>()>;
classFactory{public:staticFactory&instance(){staticFactory f;returnf;}voidregisterCreator(std::string key,Creator creator){creators_.emplace(std::move(key),std::move(creator));}std::unique_ptr<Base>create(conststd::string&key)const{returncreators_.at(key)();}private:std::unordered_map<std::string,Creator>creators_;};

2. 自动注册(推荐)

template<typenameT>structAutoRegister{AutoRegister(conststd::string&key){Factory::instance().registerCreator(key,[]{returnstd::make_unique<T>();});}};
classImplA:publicBase{public:voidrun()override{}};staticAutoRegister<ImplA>regA("A");

优点

  • 零侵入
  • 插件友好
  • 新增类型无需改工厂

3. 为什么这是“现代”写法?

  • 使用unique_ptr明确所有权
  • Lambda 消除样板代码
  • static局部变量保证线程安全(C++11+)
  • 完全 OCP

三、带参数的现代工厂写法(非常常见)

1. 问题

构造函数有参数:

ImplA(intw,doubles);

2. 推荐方案:参数对象(Parameter Object)

structConfig{intwidth;doublescale;};
usingCreator=std::function<std::unique_ptr<Base>(constConfig&)>;
classFactory{public:voidregisterCreator(std::string key,Creator c){creators_[key]=std::move(c);}std::unique_ptr<Base>create(conststd::string&key,constConfig&cfg)const{returncreators_.at(key)(cfg);}private:std::unordered_map<std::string,Creator>creators_;};
Factory::instance().registerCreator("A",[](constConfig&cfg){returnstd::make_unique<ImplA>(cfg.width,cfg.scale);});

工程价值

  • 构造参数可扩展
  • 工厂接口稳定
  • 不破坏 ABI

四、C++20 改进:Concept + 工厂

适合大型工程 / 库级代码

template<typenameT>conceptProduct=std::derived_from<T,Base>&&std::default_initializable<T>;
template<Product T>voidregisterType(std::string key){Factory::instance().registerCreator(std::move(key),[]{returnstd::make_unique<T>();});}

收益

  • 编译期约束
  • 错误更早暴露
  • 接口自文档化

五、高性能版本:无std::function

当工厂在热路径中被频繁调用:

1. 问题

  • std::function可能引入堆分配
  • 虚调用 + 间接跳转

2. 解决方案:函数指针 / 模板表

usingCreator=std::unique_ptr<Base>(*)();
template<typenameT>std::unique_ptr<Base>createImpl(){returnstd::make_unique<T>();}
creators_["A"]=&createImpl<ImplA>;

权衡

  • 性能更优
  • 灵活性略降
  • 适合内核模块

六、编译期工厂(零运行期开销)

当类型集合在编译期固定

template<typenameT>std::unique_ptr<Base>create(){returnstd::make_unique<T>();}

调用方:

autoobj=create<ImplA>();

适合

  • 算法内核
  • 无运行期配置
  • 性能敏感路径

七、工厂 + 插件系统(dlopen)

典型结构:

Factory (主程序) ↑ PluginA.so → register("A") PluginB.so → register("B")

插件加载时执行:

extern"C"voidregisterPlugin(){Factory::instance().registerCreator("A",[]{returnstd::make_unique<ImplA>();});}

这是现代大型 C++ 系统最常见的用法之一。


八、现代 C++ 工厂的反例(请避免)

返回裸指针

Base*create();

工厂中塞业务逻辑

createAndRunAndValidate();

构造参数散落

create(int,int,double,bool);

九、快速选型总结

场景推荐方案
配置驱动注册式工厂
插件系统自动注册
性能敏感函数指针工厂
编译期固定模板工厂
API/SDKConcept + Factory

十、总结

现代 C++ 的工厂模式,本质是:
用类型系统 + RAII + 注册机制,
将“变化”限制在最小边界内。


一个真实 SLAM 模块的完整工厂实现

示例模块:FeatureExtractor


一、模块目标与设计边界

1. 目标

  • 支持多种特征提取算法(ORB / FAST / SuperPoint)
  • 通过配置文件选择实现
  • 不修改核心逻辑即可新增算法
  • 生命周期与 SLAM 系统一致

2. 架构位置(典型 SLAM)

Frontend ├── FeatureExtractor ← 工厂创建 ├── FeatureMatcher └── Tracker

FeatureExtractor 是典型“策略可替换模块”


二、接口定义

feature_extractor.h

#pragmaonce#include<vector>#include<opencv2/core.hpp>structFeature{cv::KeyPoint keypoint;cv::Mat descriptor;};classFeatureExtractor{public:virtual~FeatureExtractor()=default;virtualstd::vector<Feature>extract(constcv::Mat&image)=0;};

设计要点

  • 纯接口
  • 无构造参数
  • 不暴露具体实现细节

三、参数对象(Config)

extractor_config.h

#pragmaonce#include<string>structExtractorConfig{std::string type;// "ORB" / "FAST" / ...intmax_features=1000;floatscale_factor=1.2f;intlevels=8;};

关键工程点

  • 构造参数集中
  • 新增参数不破坏工厂接口
  • 易于 YAML / JSON 映射

四、具体实现(变化层)

orb_extractor.h

#pragmaonce#include"feature_extractor.h"#include"extractor_config.h"classORBExtractorfinal:publicFeatureExtractor{public:explicitORBExtractor(constExtractorConfig&cfg);std::vector<Feature>extract(constcv::Mat&image)override;private:intmax_features_;floatscale_factor_;intlevels_;};

orb_extractor.cpp

#include"orb_extractor.h"ORBExtractor::ORBExtractor(constExtractorConfig&cfg):max_features_(cfg.max_features),scale_factor_(cfg.scale_factor),levels_(cfg.levels){}std::vector<Feature>ORBExtractor::extract(constcv::Mat&image){std::vector<Feature>features;// ORB extraction logic...returnfeatures;}

五、工厂定义(核心)

feature_extractor_factory.h

#pragmaonce#include<memory>#include<unordered_map>#include<functional>#include<string>#include"feature_extractor.h"#include"extractor_config.h"classFeatureExtractorFactory{public:usingCreator=std::function<std::unique_ptr<FeatureExtractor>(constExtractorConfig&)>;staticFeatureExtractorFactory&instance();voidregisterCreator(conststd::string&type,Creator creator);std::unique_ptr<FeatureExtractor>create(constExtractorConfig&cfg)const;private:FeatureExtractorFactory()=default;std::unordered_map<std::string,Creator>creators_;};

feature_extractor_factory.cpp

#include"feature_extractor_factory.h"#include<stdexcept>FeatureExtractorFactory&FeatureExtractorFactory::instance(){staticFeatureExtractorFactory factory;returnfactory;}voidFeatureExtractorFactory::registerCreator(conststd::string&type,Creator creator){creators_[type]=std::move(creator);}std::unique_ptr<FeatureExtractor>FeatureExtractorFactory::create(constExtractorConfig&cfg)const{autoit=creators_.find(cfg.type);if(it==creators_.end()){throwstd::runtime_error("Unknown FeatureExtractor type: "+cfg.type);}returnit->second(cfg);}

六、自动注册(工程关键技巧)

extractor_register.h

#pragmaonce#include"feature_extractor_factory.h"template<typenameT>structExtractorRegistrar{ExtractorRegistrar(conststd::string&type){FeatureExtractorFactory::instance().registerCreator(type,[](constExtractorConfig&cfg){returnstd::make_unique<T>(cfg);});}};

orb_register.cpp

#include"orb_extractor.h"#include"extractor_register.h"staticExtractorRegistrar<ORBExtractor>reg_orb("ORB");

重要工程特性

  • 无需修改工厂

  • 新算法只需:

    • 新类
    • 新.cpp注册文件

七、系统使用方式

ExtractorConfig cfg;cfg.type="ORB";cfg.max_features=1500;autoextractor=FeatureExtractorFactory::instance().create(cfg);autofeatures=extractor->extract(image);

此处 Frontend 完全不知道 ORB 的存在


八、为什么这是“真实 SLAM 工厂实现”

1. 满足真实工程需求

  • 算法频繁切换
  • 配置驱动
  • 生命周期清晰
  • 可测试、可扩展

2. 与 SLAM 实际复杂度匹配

  • 不引入 DI 框架
  • 不过度模板化
  • 不牺牲可读性

3. 易于扩展为插件系统

libslam_core.so liborb_extractor.so libsuperpoint_extractor.so

每个插件在加载时完成注册。


九、常见坑(真实踩坑总结)

1. 静态初始化顺序问题

问题: 注册对象在工厂之前初始化
方案: 使用instance()的局部静态


2. 工厂里塞逻辑

问题: 工厂决定参数
方案: 参数由 Config 决定


3. 返回裸指针

问题: 生命周期不明确
方案:std::unique_ptr


十、总结

在真实 SLAM 系统中,
工厂不是“设计模式练习”,
而是“算法可演化性的基础设施”。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/12 5:37:33

结构化输出怎么做?OpenCSG公益课实战

由特许全球金融科技师CGFT认证项目&#xff08;Chartered Global FinTech) 、模速空间与OpenCSG&#xff08;开放传神&#xff09;联合推出《普通人的AI掘金课——6天学会&#xff0c;马上能用》系列直播课程&#xff0c;提供了一个非常工程化的视角&#xff1a;当AI参与到“可…

作者头像 李华
网站建设 2026/10/12 4:49:13

2026版Java面试题库及答案解析

今年的行情&#xff0c;让招聘面试变得雪上加霜。已经有不少大厂&#xff0c;如腾讯、字节跳动的招聘名额明显减少&#xff0c;面试门槛却一再拔高&#xff0c;如果不用心准备&#xff0c;很可能就被面试官怼得哑口无言&#xff0c;甚至失去了难得的机会。 现如今&#xff0c;…

作者头像 李华
网站建设 2026/10/9 16:10:20

计算机毕业设计springboot网络云盘系统的设计与实现 基于Spring Boot框架的网络云存储系统开发与实现 Spring Boot驱动的网络云盘系统设计与开发实践

计算机毕业设计springboot网络云盘系统的设计与实现_10f66&#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。随着信息技术的飞速发展&#xff0c;网络云盘系统已成为现代信息管理的…

作者头像 李华
网站建设 2026/10/12 9:56:52

疆鸿智能ETHERCAT从站转DEVICENET主站详细解读,建议点赞收藏术语

疆鸿智能ETHERCAT从站转DEVICENET主站详细解读&#xff0c;建议点赞收藏 术语 DeviceNet&#xff1a;DeviceNet是ODVA推出基于CAN的一种通讯规范 EtherCAT&#xff1a;EtherCAT&#xff08;以太网控制自动化技术&#xff09;是一个开放架构&#xff0c;以以太网为基础的现场…

作者头像 李华
网站建设 2026/10/11 7:54:35

A5E00878652(西门子)SINAMICS Powerblock核心特性与应用

A5E00878652是西门子SINAMICS系列专用Powerblock功率模块&#xff0c;专为中小功率变频驱动场景设计&#xff0c;作为核心动力转换单元&#xff0c;聚焦电能高效变流、电机精准调速与工业级稳定运行&#xff0c;广泛应用于小型风机水泵、包装机械、暖通空调及OEM自动化设备&…

作者头像 李华
网站建设 2026/10/11 17:03:51

2026年轨道轴承市场报告:行业现状、驱动因素与未来发展趋势深度解析

轨道轴承&#xff0c;又称铁路轴承或轨道交通专用滚动轴承&#xff0c;主要用于支撑车轴并减少轮轨之间的摩擦阻力。与普通工业轴承相比&#xff0c;轨道轴承需承受更高的载荷、更频繁的冲击以及极端温差环境&#xff0c;因此对材料强度、密封性、润滑性能和疲劳寿命有严苛要求…

作者头像 李华