繁体   English   中英

从QString到Class类型

[英]From QString to Class type

我有很多类都是从同一个父类派生的,并且需要从简单的QString实例化那些类。

我想象过使用带有QString键的QMap并将类的“引用”作为值可以解决问题

class Feat : public QObject { ... } // Base class

QMap<QString, ...> feats;

但是我不知道如何从这里走,得到我想要的语法是什么。

假设您的类继承自QObject ,则可以使用QMetaType系统从其名称将实例构造为字符串。 元对象系统是Qt的关键部分,并提供了类型名称和类型ID之间的映射。

您需要首先注册您的类型,以便元对象系统知道如何使用以下方法来处理它:

Q_DECLARE_METATYPE(Feat)

然后,每当要通过对象名称构造对象时,都可以使用:

int type_id = QMetaType::type("Feat");
void *obj = QMetaType::create(type_id);

现在, obj指向Feat的动态分配实例。 请注意,完成后需要释放对象(使用QMetaType::destroy(type_id, obj); ); 将其包装在某种受保护的指针中( std::unique_ptrQPointer等); 或确保它具有QObject父级,它将自动释放它。

另外,请注意,您需要注册要以这种方式使用的每种类型。

由于构造函数不是“常规”函数,因此需要类似工厂模式的东西,即存储返回给定类型的新实例的函数。 一个简单的C ++ 11 +实现方法是将QString映射到返回新实例(作为指向基类的指针)的std::function

QMap<QString, std::function<Feat *()>> feats;
feats["Feat1"] = []() { return new Feat1; };
feats["Feat2"] = []() { return new Feat2; };

如果需要传递参数以进行构造,或者如果您希望返回一些智能指针(例如, unique_ptr ),请根据需要进行调整。 另外,根据您的喜好,您可能会或可能不喜欢将代码隐藏在宏后面。

#define REGISTER_FEAT(FeatClass) feats[#FeatClass] = []() { return new FeatClass;}
// to be used as
REGISTER_FEAT(Feat1);
REGISTER_FEAT(Feat2);

如果您确定不需要捕获这些lambda中的任何内容,也可以避免std::function开销,但是除非您有真正的理由(构建时间或运行时开销?)来避免,否则我不会担心这一点它。


顺便说一句,即使Digia也将Qt容器确认为“生命支持模式”,所以,除非您有充分的理由使用它们(例如,稳定的二进制接口,不同编译器之间的性能更一致-尽管通常更糟),否则通常会为您提供更好的服务由内置的“ STL”副本(例如std::mapstd::unordered_map )表示。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM