C++反射机制入门
·
以下是基于纯C++标准(仅依赖g++编译器)的反射机制入门详解,包含三种可编译的实用方案,每种方案均提供完整代码和编译命令:
🔧 一、工厂模式+注册宏(动态创建对象)
适用场景:插件系统、动态加载类
原理:全局映射表存储类名与构造函数,通过字符串实例化对象
代码示例(C++11起支持):
#include <iostream>
#include <unordered_map>
#include <functional>
#include <memory>
class Factory {
using Creator = std::function<std::unique_ptr<void>()>;
static std::unordered_map<std::string, Creator> registry;
public:
static void registerClass(const std::string& name, Creator fn) {
registry[name] = fn;
}
template <typename T>
static std::unique_ptr<T> create(const std::string& name) {
auto it = registry.find(name);
if (it != registry.end()) {
auto basePtr = it->second();
void* rawPtr = basePtr.release();
return std::unique_ptr<T>(static_cast<T*>(rawPtr));
}
return nullptr;
}
};
std::unordered_map<std::string, Factory::Creator> Factory::registry;
// 自动注册宏(在main前初始化)
#define REGISTER_CLASS(ClassName) \
namespace { \
struct ClassName##Register { \
ClassName##Register() { \
Factory::registerClass(#ClassName, []() -> std::unique_ptr<void> { \
return std::unique_ptr<void>(new ClassName()); \
}); \
} \
}; \
static ClassName##Register ClassName##_register; \
}
// 测试类
class MyClass {
public:
void print() { std::cout << "MyClass created\n"; }
};
REGISTER_CLASS(MyClass) // 注册
int main() {
auto obj = Factory::create<MyClass>("MyClass");
if (obj) obj->print(); // 输出:MyClass created
return 0;
}
编译命令(需C++11):
g++ -std=c++11 -o reflect factory.cpp
🧠 二、编译时反射(类型信息查询)
适用场景:序列化框架、代码生成
原理:模板特化+constexpr在编译时生成类型元数据
代码示例(C++17起支持):
#include <iostream>
#include <string_view>
// 反射模板基类
template <typename T>
struct Reflect {
static constexpr size_t member_count = 0;
static constexpr std::string_view member_name(size_t) { return ""; }
};
// 目标类
struct Person {
int age;
std::string name;
};
// 特化Person的反射信息
template <>
struct Reflect<Person> {
static constexpr size_t member_count = 2;
static constexpr std::string_view member_name(size_t i) {
constexpr std::string_view names[] = {"age", "name"};
return (i < member_count) ? names[i] : "";
}
};
// 打印类型信息
template <typename T>
void print_type_info() {
std::cout << "Members of " << typeid(T).name() << ":\n";
for (size_t i = 0; i < Reflect<T>::member_count; ++i) {
std::cout << " - " << Reflect<T>::member_name(i) << "\n";
}
}
int main() {
print_type_info<Person>();
// 输出:
// Members of Person:
// - age
// - name
return 0;
}
编译命令(需C++17):
g++ -std=c++17 -o reflect compile_time.cpp
📦 三、成员变量映射(运行时属性访问)
适用场景:对象序列化、动态属性查看器
原理:基类维护成员指针映射表
代码示例(C++11起支持):
#include <iostream>
#include <string>
#include <unordered_map>
class Reflectable {
protected:
std::unordered_map<std::string, void*> property_map;
public:
template <typename T>
void register_property(const std::string& name, T& prop) {
property_map[name] = ∝
}
void print_property(const std::string& name) {
if (auto it = property_map.find(name); it != property_map.end()) {
std::cout << name << " = " << *(static_cast<std::string*>(it->second)) << "\n";
}
}
};
class User : public Reflectable {
public:
std::string username;
int id;
User() : username(""), id(0) {
register_property("username", username);
// 扩展点:可添加其他属性注册
}
};
int main() {
User user;
user.username = "Alice";
user.print_property("username"); // 输出:username = Alice
return 0;
}
编译命令:
g++ -std=c++11 -o reflect member_map.cpp
⚖️ 方案对比与选型建议
| 方案 | 技术特点 | 适用场景 | 编译要求 |
|---|---|---|---|
| 工厂模式+注册宏 | 运行时动态创建对象 | 插件系统、动态加载 | C++11 |
| 编译时反射 | 零运行时开销,类型安全 | 序列化框架、代码生成器 | C++17 |
| 成员变量映射 | 显式注册属性,灵活性高 | 对象序列化、属性查看器 | C++11 |
⚠️ 避坑指南:
- 全局静态变量初始化顺序:工厂模式中注册宏需在
main前执行(利用静态变量初始化机制)- 类型安全:工厂模式中
static_cast转换需确保类型匹配,否则UB- 编译时反射限制:无法获取运行时对象值,仅适合类型元数据
更多推荐




所有评论(0)