stevenyao

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  22 随笔 :: 1 文章 :: 67 评论 :: 0 Trackbacks
理论上 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的动态创建简单多少。。。

posted on 2010-01-09 13:44 姚冬 阅读(2389) 评论(1)  编辑 收藏 引用

评论

# re: 用QMetaType动态创建一个 QWidget 2010-01-11 22:59 淘宝皇冠大全
按开始的骄傲  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理