从QString到Class类型

时间:2019-01-01 21:04:12

标签: c++ qt class

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

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

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

QMap<QString, ...> feats;

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

2 个答案:

答案 0 :(得分:1)

鉴于您的类继承自QObject,因此您可以使用QMetaType system从其名称构造实例作为字符串。元对象系统是Qt的关键部分,它提供了名称类型和 IDs 类型之间的映射。

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

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父级,它将自动释放它。

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

答案 1 :(得分:0)

由于构造函数不是“常规”函数,因此您需要类似工厂模式的东西,即存储返回给定类型新实例的函数;一种简单的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)通常可以更好地为其提供服务。