用QMetaType动态创建一个 QWidget

用QMetaType动态创建一个 QWidget
理论上 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的动态创建简单多少。。。

你可能感兴趣的:(用QMetaType动态创建一个 QWidget)