以下是 Qt 中常用的宏和函数分类详解:
元对象系统(Meta-Object System)
1.Q_OBJECT
-
作用:启用类的信号槽、属性系统、动态翻译等特性。
-
必须放在类的私有部分,且需要运行 moc(元对象编译器)预处理。
-
示例:
class MyClass : public QObject {
Q_OBJECT // 必须添加
public:
// ...
};
2.Q_PROPERTY
-
作用:声明类的属性,支持动态访问(通过
property()和setProperty())。 -
参数:属性名、类型、读写函数、通知信号等。
-
示例:
Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
3.Q_INVOKABLE
-
作用:标记成员函数可从元对象系统调用(如 QML 或
invokeMethod())。
示例:
Q_INVOKABLE void updateData();
信号与槽(Signals & Slots)
1.signals
-
作用:声明信号(无需实现,由 moc 生成)。
-
示例:
signals:
void valueChanged(int newValue);
2.slots
-
作用:声明槽函数(可以是
public、protected或private)。 -
示例:
public slots:
void onButtonClicked();
3.emit
-
作用:触发信号(实际是宏,展开为普通函数调用)。
-
示例:
emit valueChanged(42);
元类型与反射(Meta-Types)
1.Q_DECLARE_METATYPE(Type)
- 作用:声明自定义类型可用于 QVariant 或跨线程信号槽。
- 需配合 qRegisterMetaType<T>() 使用。
- 使用场景:需要在信号槽(跨线程)或 QVariant 中使用自定义类型时。
- 要求:类型必须是可拷贝的(具有公有的拷贝构造函数和析构函数)。
- 示例
struct MyStruct { int id; QString name; };
Q_DECLARE_METATYPE(MyStruct) // 声明后可在信号槽或QVariant中使用
2.qRegisterMetaType<T>("TypeName")
-
作用:运行时注册元类型(跨线程信号槽必需)。
-
与
Q_DECLARE_METATYPE的关系:-
Q_DECLARE_METATYPE是编译期声明,qRegisterMetaType是运行时注册。 -
跨线程信号槽必须调用
qRegisterMetaType。
-
-
示例:
qRegisterMetaType<MyStruct>("MyStruct"); // 注册到元对象系统
3.Q_ENUM / Q_ENUM_NS
-
作用:将枚举注册到元对象系统,支持字符串转换。
-
示例:
enum Color { Red, Green, Blue };
Q_ENUM(Color) // 允许 QMetaEnum::fromType<Color>()
插件与接口(Plugins & Interfaces)
1.Q_DECLARE_INTERFACE(Interface, IID)
-
作用:声明接口类,
IID是唯一标识符(通常为反向域名格式)。 -
示例:
Q_DECLARE_INTERFACE(MyPluginInterface, "com.example.MyPlugin")
2.Q_INTERFACES(Interface1 Interface2...)
1.作用:在插件实现类中声明实现的接口。
2.使用场景:
开发插件时,在实现接口的类中标记其支持的接口。
3.必须与 Q_DECLARE_INTERFACE 配对使用:
接口定义处用 Q_DECLARE_INTERFACE,实现类用 Q_INTERFACES。
3.Q_PLUGIN_METADATA(IID "InterfaceID" FILE "metadata.json")
-
作用:标记类为插件,并指定接口 ID(通常与
Q_INTERFACES共用)。 -
关键参数:
-
IID:插件接口的唯一标识符(必须与加载器匹配)。 -
FILE:可选的 JSON 文件,描述插件版本、作者等元信息
-
4. 示例
1.定义接口:
// 接口类声明
class MyInterface { ... };
Q_DECLARE_INTERFACE(MyInterface, "com.example.MyInterface") // 声明接口
2. 实现插件:
class MyPlugin : public QObject, public MyInterface {
Q_OBJECT
Q_INTERFACES(MyInterface) // 声明实现的接口
Q_PLUGIN_METADATA(IID "com.example.MyInterface") // 标记为插件
// 实现接口方法...
};
国际化(Internationalization)
1.Q_DECLARE_TR_FUNCTIONS(ClassName)
-
作用:为类添加
tr()函数,用于字符串翻译。 -
示例:
class MyClass {
Q_DECLARE_TR_FUNCTIONS(MyClass)
public:
QString msg = tr("Hello"); // 可被翻译
};
2. QT_TR_NOOP / QT_TRANSLATE_NOOP
-
作用:标记待翻译字符串(不立即翻译,需配合
.ts文件使用)。
调试与日志
1.QDebug 相关宏
-
qDebug(),qInfo(),qWarning(),qCritical(),qFatal() -
示例
qDebug() << "Current value:" << value;
Q_ASSERT / Q_ASSERT_X
-
作用:调试断言(失败时输出错误信息)。
平台与编译器特性
-
Q_DECL_EXPORT/Q_DECL_IMPORT-
作用:标记动态库的导出/导入符号(跨平台兼容)。
-
-
Q_UNUSED(var)-
作用:抑制未使用变量的编译器警告。
-
其他常用宏
-
foreach (var, container)-
作用:Qt 风格的循环(C++11 后推荐用范围 for)。
-
-
Q_NULLPTR-
作用:跨平台的
nullptr替代(Qt 4 兼容性)。
-
-
Q_DISABLE_COPY(Class)-
作用:禁用类的拷贝构造和赋值操作(常用于 QObject 派生类)。
-
示例代码
#include <QObject>
#include <QDebug>
class MyPluginInterface {
public:
virtual ~MyPluginInterface() {}
virtual void doWork() = 0;
};
Q_DECLARE_INTERFACE(MyPluginInterface, "org.example.MyPlugin")
class MyPlugin : public QObject, public MyPluginInterface {
Q_OBJECT
Q_INTERFACES(MyPluginInterface)
Q_PLUGIN_METADATA(IID "org.example.MyPlugin")
public:
Q_INVOKABLE void doWork() override {
qDebug() << "Plugin working...";
}
};
// 自定义类型使用
struct Point { int x; int y; };
Q_DECLARE_METATYPE(Point)
核心区别总结
| 宏/函数 | 阶段 | 用途 | 依赖关系 |
|---|---|---|---|
Q_DECLARE_METATYPE | 编译期 | 声明元类型(用于信号槽/QVariant) | 需配合 qRegisterMetaType |
qRegisterMetaType | 运行时 | 注册元类型(跨线程必需) | 需先声明 Q_DECLARE_METATYPE |
Q_INTERFACES | 编译期 | 声明类实现的接口 | 需接口已用 Q_DECLARE_INTERFACE 声明 |
Q_PLUGIN_METADATA | 编译期 | 标记插件类并添加元数据 | 通常与 Q_INTERFACES 共用 |
常见问题
1. 为什么跨线程信号槽需要 qRegisterMetaType?
Qt 需要在运行时动态创建类型的副本,未注册的类型会导致 "Unknown type" 错误。
2. Q_PLUGIN_METADATA 的 JSON 文件有什么用?
提供插件的元信息(如描述、版本号),可通过 QPluginLoader 读取。
3. 接口和插件的关系?
接口定义行为,插件是实现接口的具体模块,通过 QPluginLoader 动态加载。
4. Q_OBJECT 必须位于头文件,且类需继承自 QObject。
使用信号槽或元对象功能时,必须运行 moc(Qt 构建系统自动处理)。
5. 跨线程信号槽传递自定义类型时,必须调用 qRegisterMetaType<T>()。
掌握这些宏和函数,能够高效利用 Qt 的元对象系统、插件机制和跨平台特性
613

被折叠的 条评论
为什么被折叠?



