我有一个库,它注册了一堆元类型,由这段代码说明:
abstractfoobase.h
namespace foo {
enum FooState { OK, MAYBE };
class AbstractFooBase : public QObject {...};
}
Q_DECLARE_METATYPE(foo::FooState)
Run Code Online (Sandbox Code Playgroud)
还有一个相应的abstractfoobase.cpp,内容取决于在基类中实现的内容.
foousingclass.h:
namespace foo {
class FooUsingClass : public AbstractFooBase {...};
}
Run Code Online (Sandbox Code Playgroud)
同样有相应的foousingclass.cpp,它有方法实现等.
现在,它Q_DECLARE_METATYPE启用了Qt模板类的类型QVariant.要启用使用排队信号中的类型等,还需要进行相应的调用:
qRegisterMetaType<foo::FooState>();
Run Code Online (Sandbox Code Playgroud)
qRegisterMetaType拨打电话的好地方是什么?我显然不希望从应用程序代码中进行任何明显的初始化调用.注册必须在做完之后发生foo::FooUsingClass *f = new foo::FooUsingClass();.
在Java中,我将这种代码放在静态初始化块中.我也可以在C++中看到几种方法来实现这一点,但是它们中没有一个看起来特别好看.例如,简单地将这些放入AbstractFooBase构造函数将导致每次创建子类实例时调用注册,这可能是不希望的开销.所以那些做过这个的人,你在哪里qRegisterMetaType打电话?
我可以想象如下:
在abstractfoobase.cpp中:
namespace foo {
/// Initializer
class FooStateInit {
public:
FooStateInit() {
qRegisterMetaType<foo::FooState>();
}
};
static FooStateInit fooStateInit;
} // namespace foo
Run Code Online (Sandbox Code Playgroud)
我最近发现了一个简单的解决方案,它也可以与静态库一起使用。
它利用了qMetaTypeId<>()整个Qt元类型系统中使用的事实。因此,通过显式的模板实例化,我们可以强制链接到abstractfoobase.cpp(否则,链接程序可能会决定是否不存在引用的符号),并确保在程序启动时静态注册该类型:
abstractfoobase.h
#include <QMetaType>
namespace foo {
enum FooState { OK, MAYBE };
}
Q_DECLARE_METATYPE(foo::FooState)
extern template int qMetaTypeId<foo::FooState>();
Run Code Online (Sandbox Code Playgroud)
abstractfoobase.cpp
static const int kFooStateMetaTypeId = qRegisterMetaType<foo::FooState>();
template int qMetaTypeId<foo::FooState>();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1127 次 |
| 最近记录: |