[英]QString::toInt() fails when converting a QString from another 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_ptr
, QPointer
等); 或确保它具有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::map
或std::unordered_map
)表示。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.