C++ 無內建反射機制,無法直接通過類名字符串創建對象。類工廠模式通過註冊表將類名映射到構造函數,實現運行時動態創建。
// 通用構造函數指針類型
using CreateFunc = void* (*)();
class DynObjectFactory {
// 類名 -> 構造函數映射表
static map registry;
public:
// 註冊類
static void Register(const string& name, CreateFunc func) {
registry[name] = func;
}
// 通過類名創建對象
static void* CreateObject(const string& name) {
auto it = registry.find(name);
return (it != registry.end()) ? it->second() : nullptr;
}
};
// 靜態成員定義(selectany 避免多重定義)
__declspec(selectany) map DynObjectFactory::registry;
class RegisterHelper {
public:
RegisterHelper(const string& name, CreateFunc func) {
DynObjectFactory::Register(name, func);
}
};
#define REGISTER_CLASS(class_name) \
class class_name##Registrar { \
public: \
static void* CreateInstance() { return new class_name; } \
private: \
static RegisterHelper registrar; \
}; \
RegisterHelper class_name##Registrar::registrar(#class_name, class_name##Registrar::CreateInstance)
class Shape {
public:
virtual void Draw() = 0;
virtual ~Shape() {}
};
class Circle : public Shape {
public:
void Draw() override { cout << "Circle::Draw()" << endl; }
~Circle() { cout << "~Circle" << endl; }
};
REGISTER_CLASS(Circle);
class Square : public Shape {
public:
void Draw() override { cout << "Square::Draw()" << endl; }
~Square() { cout << "~Square" << endl; }
};
REGISTER_CLASS(Square);
class Rectangle : public Shape {
public:
void Draw() override { cout << "Rectangle::Draw()" << endl; }
~Rectangle() { cout << "~Rectangle" << endl; }
};
REGISTER_CLASS(Rectangle);
void DrawAll(const vector& shapes) { for (auto* s : shapes) s->Draw(); } void DeleteAll(const vector & shapes) { for (auto* s : shapes) delete s; } int main() { vector shapes; // 通過字符串動態創建 shapes.push_back(static_cast (DynObjectFactory::CreateObject("Circle"))); shapes.push_back(static_cast (DynObjectFactory::CreateObject("Square"))); shapes.push_back(static_cast (DynObjectFactory::CreateObject("Rectangle"))); DrawAll(shapes); DeleteAll(shapes); return 0; }
Circle::Draw() Square::Draw() Rectangle::Draw() ~Circle ~Square ~Rectangle
RegisterHelper 全局對象構造時自動註冊,無需手動調用class_name##Registrar 避免多類註冊衝突std::function + std::any 或變參模板dlopen/LoadLibrary)