理论上 QWidget及其派生类是不可以用 Q_DECLARE_METATYPE(QWidget); 的,因为你 写下这样的代码编译通不过
会报告一个 :error C2248: 'QWidget::QWidget' : cannot access private member declared in class 'QWidget'
原因在于 QWidget里 有 Q_DISABLE_COPY(QWidget),所以把拷贝构造和等号赋值都私有化了,但是Q_DECLARE_METATYPE里面需要访问拷贝构造
因为 Q_DECLARE_METATYPE 需要构建一个 Constructor
代码如下:
template<typename T>
void *qMetaTypeConstructHelper(const T *t)
{
if (!t)
return new T;
return new T(*static_cast(t)); //此处需要访问拷贝构造函数,从而造成编译错误
}
即使实际运行时候我并不需要拷贝构造,但是编译时是需要,所以无法编译。
有个方法可以欺骗编译器,就是给QWidget类写一个 qMetaTypeConstructHelper的特化版本
声明成 Static 是为了避免link error
代码如下:
template <>
static void *qMetaTypeConstructHelper(const QWidget *t)
{
return new QWidget();
}
Q_DECLARE_METATYPE(QWidget);
于是这样就可以创建 QWidget了,代码如下:
QWidget *w= static_cast< QWidget*>(QMetaType::construct(qMetaTypeId()));
//或者
qRegisterMetaType("QWidget");
QWidget *w= static_cast< QWidget*>(QMetaType::construct(QMetaType::type("QWidget")));
这种方法是可以欺骗编译器,并且可以达到动态创建的目的,但是并不等于我推荐这样的做法,实际上这样做并不比你为每个类名称写if else的动态创建简单多少。。。