目录
官方解释
Q_DECLARE_METATYPE(Type)
这个宏是为了让QMetaType知道Type这个数据类型,并提供一个默认的拷贝构造函数和析构函数。QVariant需要使用Q_DECLARE_METATYPE这个宏来定制类型。
当使用这个宏的时候要求Type是一个完整的数据类型。可以使用Q_DECLARE_OPAQUE_POINTER()来注册一个指针用于转发声明类型。
一般都把这个宏放到结构体或类的末尾【注意:这是官方说的】,如果不放到末尾也是阔以的,就放到头文件中,当你用 QVariant就要包含那个.h,个人觉得这非常不适合面向对象以及模块化编程。
通过添加Q_DECLARE_METATYPE()这个宏让QOject及其子类知道这个类型。这里要注意的是如果要在队列信号(关于connect函数队列信号请看这篇博文:https://blog.csdn.net/qq78442761/article/details/81937837)中使用或者用用槽连接,要先调用这个函数qRegisterMetaType()【这里是在运行的时候,对他进行注册】
下面是官方给出的一个小栗子:
struct MyStruct
{
int i;
...
};
Q_DECLARE_METATYPE(MyStruct)
栗子二:
namespace MyNamespace
{
...
}
Q_DECLARE_METATYPE(MyNamespace::MyStruct)
以及如何在QVariant中使用的栗子:
MyStruct s;
QVariant var;
var.setValue(s); // copy s into the variant
...
// retrieve the value
MyStruct s2 = var.value<MyStruct>();
下面这几个类型是自动注册的,不需要使用Q_DECLARE_METATYPE这个宏:
1.QObject继承下来的子类的指针;
2.QList<T>, QVector<T>, QQueue<T>, QStack<T>, QSet<T> or QLinkedList<T>这些T都是自动注册的;
3.QHash<T1, T2>, QMap<T1, T2> or QPair<T1, T2> T1,和T2都是自动注册的;
4.QPointer<T>, QSharedPointer<T>, QWeakPointer<T>这3个T必须是QObject的子类;
5.枚举类型要用Q_ENUM or Q_FLAG;
6.拥有Q_GADGET宏的类。
下面是我自己的例子,用于对Q_DECLARE_METATYPE这一知识点的补充!
博主补充小栗子
最简单的关于Q_DECLARE_METATYPE的例子:
源码如下:
mydatatype.h
#ifndef MYDATATYPE_H
#define MYDATATYPE_H
#include <QMetaType>
class MyDataType
{
public:
MyDataType();
int value_a;
int value_b;
int value_c;
};
Q_DECLARE_METATYPE(MyDataType)
#endif // MYDATATYPE_H
main.cpp
#include <QApplication>
#include "mydatatype.h"
#include <QVariant>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyDataType *myDataType=new MyDataType;
QVariant var;
var.setValue(*myDataType);
qDebug()<<var;
MyDataType my=var.value<MyDataType>();
qDebug()<<my.value_a<<" "<<my.value_b<<" "<<my.value_c;
delete myDataType;
return a.exec();
}
mydatatype.cpp
#include "mydatatype.h"
MyDataType::MyDataType()
{
value_a=0;
value_b=1;
value_c=2;
}
运行截图如下:
关于qRegisterMetaType的栗子
关于qRegisterMetaType的解释,在明天将会给出官方的详细说明,在此先会用就阔以了!
源码如下:
mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
namespace Ui {
class MyWidget;
}
struct MyData{
QString str;
};
Q_DECLARE_METATYPE(MyData)
class MyWidget : public QWidget
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = 0);
~MyWidget();
signals:
void sendData(MyData myWidget);
public slots:
void textChanged(QString str);
private:
Ui::MyWidget *ui;
QString m_str;
};
#endif // MYWIDGET_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "mywidget.h"
class MyWidget;
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
public slots:
void btnClicked();
void receiverData(MyData var);
private:
Ui::Widget *ui;
MyWidget *m_mywidget;
};
#endif // WIDGET_H
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
mywidget.cpp
#include "mywidget.h"
#include "ui_mywidget.h"
#include <QDebug>
MyWidget::MyWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::MyWidget)
{
ui->setupUi(this);
connect(ui->lineEdit,SIGNAL(textChanged(QString)),this,SLOT(textChanged(QString)));
qRegisterMetaType<MyData>();
}
MyWidget::~MyWidget()
{
delete ui;
}
void MyWidget::textChanged(QString str)
{
MyData myData;
myData.str=str;
sendData(myData);
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
m_mywidget=new MyWidget;
connect(ui->pushButton,SIGNAL(clicked(bool)),this,SLOT(btnClicked()));
connect(m_mywidget,SIGNAL(sendData(MyData)),this,SLOT(receiverData(MyData)),Qt::QueuedConnection);
}
Widget::~Widget()
{
delete ui;
}
void Widget::btnClicked()
{
m_mywidget->show();
}
void Widget::receiverData(MyData var)
{
ui->lineEdit->setText(var.str);
}
运行截图如下:
继承于QObject的类,我就不演示了,因为C/C++中有个赋值兼容的知识点,估计就是通过这个赋值兼容,使得继承于QObject的类,QMetaType直接能够识别!自己进加到他的元对象系统!!!