news 2026/7/22 4:45:09

C++ 运行时反射系统设计与实现(无 RTTI)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ 运行时反射系统设计与实现(无 RTTI)

一、引言

在很多高级语言(如 C#/Java)中,“反射”是一种内省机制,允许程序在运行时查看和操作对象的结构与行为(如类名、字段、方法等)。而 C++ 作为静态语言,默认并不支持强反射机制

尽管 C++ 提供 RTTI(如typeiddynamic_cast),但其功能非常有限,并且很多高性能或嵌入式环境都禁用了 RTTI。

本文将从零开始,实现一个纯 C++ 的运行时反射系统,不依赖 RTTI,可实现字段注册、类型名称、对象属性遍历、动态构造等能力。


二、反射系统的应用场景

场景用途
编辑器属性面板展示与绑定
脚本接口反射 C++ 对象给 Lua/Python
序列化将对象自动转为 JSON/XML/Binary
插件系统不同模块之间的统一字段解析与操作
网络通信自动化消息结构注册与生成

三、目标功能概览

我们的运行时反射系统应具备以下能力:

  • 注册类型信息(类名、字段)

  • 动态构造对象(new 及析构)

  • 遍历字段,获取/设置值

  • 查询字段类型、名称、偏移量

  • 跨模块兼容性(不依赖 RTTI)


四、核心设计思路

设计三个核心类:

  1. Type:表示一个类的信息

  2. Field:表示类的一个字段(属性)

  3. TypeRegistry:集中管理所有注册的类型

我们通过宏 + 模板封装类信息,在运行时自动注册。


五、字段描述结构 Field

cpp复制编辑struct Field { std::string name; std::string type; size_t offset; template<typename T> T& get(void* instance) const { return *reinterpret_cast<T*>((char*)instance + offset); } };

六、类型信息结构 Type

cpp复制编辑struct Type { std::string name; size_t size; std::function<void*(void)> creator; std::function<void(void*)> deleter; std::vector<Field> fields; void* create() const { return creator(); } void destroy(void* obj) const { deleter(obj); } };

七、注册表 TypeRegistry

cpp复制编辑class TypeRegistry {public: static TypeRegistry& instance() { static TypeRegistry inst; return inst; } void registerType(const std::string& name, const Type& t) { types_[name] = t; } const Type* get(const std::string& name) const { auto it = types_.find(name); return it != types_.end() ? &it->second : nullptr; }private: std::unordered_map<std::string, Type> types_; };

八、反射注册宏与辅助函数

cpp复制编辑#define BEGIN_REFLECT(T) \ namespace { \ struct T##_Reflector { \ T##_Reflector() { \ Type t; \ t.name = #T; \ t.size = sizeof(T); \ t.creator = []() -> void* { return new T(); }; \ t.deleter = [](void* obj) { delete (T*)obj; };#define REFLECT_FIELD(field, type) \ t.fields.push_back(Field{#field, #type, offsetof(T, field)});#define END_REFLECT(T) \ TypeRegistry::instance().registerType(#T, t); \ } \ }; static T##_Reflector global_reflector_##T; }

九、定义一个可反射的类

cpp复制编辑struct Person { std::string name; int age; float height; };BEGIN_REFLECT(Person) REFLECT_FIELD(name, std::string) REFLECT_FIELD(age, int) REFLECT_FIELD(height, float)END_REFLECT(Person)

十、使用反射 API

cpp复制编辑void demo_reflect() { const Type* t = TypeRegistry::instance().get("Person"); if (!t) return; void* obj = t->create(); for (const Field& f : t->fields) { std::cout << "Field: " << f.name << ", Type: " << f.type << std::endl; if (f.name == "age") { f.get<int>(obj) = 30; } } Person* p = (Person*)obj; std::cout << "Person.age = " << p->age << std::endl; t->destroy(obj); }

输出结果:

yaml复制编辑Field: name, Type: std::stringField: age, Type: intField: height, Type: floatPerson.age = 30

十一、扩展方向建议

功能实现方式说明
反射方法(成员函数)可通过std::function<void(void*)>储存
继承关系反射Type 中添加 base_class_name 字段
JSON 自动序列化使用字段遍历 +std::ostringstream
属性读写回调添加 Getter/Setter 函数映射
多模块反射(DLL)用注册表为跨模块插件通信提供基础

十二、与 RTTI 的比较

特性RTTI (typeid)自定义反射系统
获取字段
获取类型名称
动态构造对象❌(需手写工厂)
可控字段注册
支持嵌入式/禁 RTTI

十三、实际应用案例

1. 自动序列化为 JSON

cpp复制编辑std::string to_json(const void* obj, const Type* t) { std::ostringstream oss; oss << "{"; for (size_t i = 0; i < t->fields.size(); ++i) { const auto& f = t->fields[i]; oss << "\"" << f.name << "\":"; if (f.type == "int") oss << f.get<int>(obj); else if (f.type == "float") oss << f.get<float>(obj); else oss << "\"" << f.get<std::string>(obj) << "\""; if (i < t->fields.size() - 1) oss << ","; } oss << "}"; return oss.str(); }

输出示例:

json复制编辑{"name":"Tom","age":30,"height":175.5}

十四、总结

本文实现了一个无 RTTI 的运行时反射系统,覆盖:

  • 字段描述与对象内存偏移

  • 类型注册与查找

  • 对象动态构造与释放

  • 字段遍历与读取设置

  • 实战序列化场景应用

该机制可轻松嵌入游戏引擎、插件框架、可视化工具中,提升系统的模块化与扩展能力。

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

成本核算模型:每千次调用消耗多少电费

成本核算模型&#xff1a;每千次调用消耗多少电费 在AI推理成本高企的今天&#xff0c;一个现实问题摆在开发者面前&#xff1a;我能不能负担得起每天成千上万次的模型调用&#xff1f;尤其是当任务只是解一道算法题或写一段函数时&#xff0c;是否真的需要动用GPT-4级别的“重…

作者头像 李华
网站建设 2026/7/15 3:39:05

8 款 AI 开题报告工具测评:让论文开篇快人 N 步

论文开题到底能多轻松&#xff1f;现在的 AI 工具已经把 “烧脑写框架” 变成了 “填空式出稿”。今天就盘点 8 款实用的 AI 开题报告工具&#xff0c;PaperXie直接拿下 “性价比王者”&#xff0c;剩下 7 款各有特色 —— 看完这篇&#xff0c;你选工具再也不用踩坑&#xff0…

作者头像 李华
网站建设 2026/7/18 14:12:26

基于springboot + vue二手电子产品系统(源码+数据库+文档)

二手电子产品 目录 基于springboot vue二手电子产品系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue二手电子产品系统 一、前言 博主介绍&…

作者头像 李华
网站建设 2026/7/14 20:59:49

基于springboot + vue嗨玩旅游网站系统(源码+数据库+文档)

健身房管理系统 目录 基于springboot vue嗨玩旅游网站系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue嗨玩旅游网站系统 一、前言 博主介绍&am…

作者头像 李华
网站建设 2026/7/17 6:29:18

BeyondCompare4对比代码太麻烦?让VibeThinker先做逻辑预处理

BeyondCompare4对比代码太麻烦&#xff1f;让VibeThinker先做逻辑预处理 在日常开发中&#xff0c;你是否曾为两段“功能相同但写法迥异”的代码而头疼&#xff1f;明明知道它们都在实现快速排序&#xff0c;可BeyondCompare4却标出几十处红色差异——变量名不同、循环结构不一…

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

蓝绿部署实践:确保线上服务无缝升级

蓝绿部署实践&#xff1a;确保线上服务无缝升级 在今天的AI服务生态中&#xff0c;模型上线早已不再是“打包上传、重启服务”那么简单。尤其当面对像 VibeThinker-1.5B-APP 这类专精于高强度推理任务的语言模型时&#xff0c;任何一次发布失误都可能直接影响用户的解题准确率、…

作者头像 李华