Qt 继承QObject时出错
我有一个类Qt 继承QObject时出错,qt,Qt,我有一个类applicationManager,当出现信息消息或错误时,它应该发出信号,而我假设通过QXmppLogger类对象记录使用它的消息。有一个QXmppLoggable类,它获得了像info()和warning()这样的方法,这些方法发出内部QXmppLogger的信号logmessage()。所以,为了发出一个信号,我继承了QXmppLogable类,它继承了QObject本身,因此能够使用info()和warning(),并通过info()和warning()方法将发出的信号(lo
applicationManager
,当出现信息消息或错误时,它应该发出信号,而我假设通过QXmppLogger类对象记录使用它的消息。有一个QXmppLoggable类,它获得了像info()
和warning()
这样的方法,这些方法发出内部QXmppLogger的信号logmessage()
。所以,为了发出一个信号,我继承了QXmppLogable类,它继承了QObject本身,因此能够使用info()
和warning()
,并通过info()和warning()方法将发出的信号(logmessage()
)连接到QXmppLogger对象的插槽(log()
)。以下是代码片段:
标题“imApplicationManager.h”
和相关的“imApplicationManager.cpp”
编译不会通知任何错误,但当出现信号错误时会通知。
如何修复此问题?您使用logger,但之前未初始化它:
QObject::connect(this, SIGNAL(logMessage(QXmppLogger::MessageType,QString)),
logger, SLOT(log(QXmppLogger::MessageType,QString)));
尝试这样重写构造函数:
applicationManagement::applicationManagement(QXmppLogger *logger_):
logger(logger_)
{
QObject::connect(this, SIGNAL(logMessage(QXmppLogger::MessageType,QString)),
logger, SLOT(log(QXmppLogger::MessageType,QString)));
}
或者在初始化记录器后连接该信号。您使用记录器,但在以下情况之前未初始化:
QObject::connect(this, SIGNAL(logMessage(QXmppLogger::MessageType,QString)),
logger, SLOT(log(QXmppLogger::MessageType,QString)));
尝试这样重写构造函数:
applicationManagement::applicationManagement(QXmppLogger *logger_):
logger(logger_)
{
QObject::connect(this, SIGNAL(logMessage(QXmppLogger::MessageType,QString)),
logger, SLOT(log(QXmppLogger::MessageType,QString)));
}
或者在初始化记录器后连接该信号。好,决定发布完整答案:
- 首先,您确实需要
宏。当您从QtCreator的Q_对象
菜单中执行Build
、Clean All
和运行qmake
时,从中获得的错误可能会消失。Qt依赖于大量生成的样板代码,您永远不必键入这些代码,如果没有Rebuild All
,则不会生成这些代码。这就是为什么您有时需要在进行更改后进行清理,运行qmake(生成代码)并使用现在最新生成的代码进行重建Q_OBJECT
- 第二个-在
的构造函数中,连接到未初始化的指针记录器。这可能就是为什么会出现分段错误。您可以使用两种方法来解决此问题:applicationManagement
- 将指针传递到
的构造函数中的记录器,这样您就可以在构造函数中连接到某个对象。这样,除非在构造函数初始化列表中使用applicationManagement
,否则无法在记录器之前实例化logger(新的QXmppLogger)
applicationManagement
- 将连接从
构造函数移动到applicationManagement
方法。不要忘记断开以前的连接(如果有)setLogger()
- 首先,您确实需要
宏。当您从QtCreator的Q_对象
菜单中执行Build
、Clean All
和运行qmake
时,从中获得的错误可能会消失。Qt依赖于大量生成的样板代码,您永远不必键入这些代码,如果没有Rebuild All
,则不会生成这些代码。这就是为什么您有时需要在进行更改后进行清理,运行qmake(生成代码)并使用现在最新生成的代码进行重建Q_OBJECT
- 第二个-在
的构造函数中,连接到未初始化的指针记录器。这可能就是为什么会出现分段错误。您可以使用两种方法来解决此问题:applicationManagement
- 将指针传递到
的构造函数中的记录器,这样您就可以在构造函数中连接到某个对象。这样,除非在构造函数初始化列表中使用applicationManagement
,否则无法在记录器之前实例化logger(新的QXmppLogger)
applicationManagement
- 将连接从
构造函数移动到applicationManagement
方法。不要忘记断开以前的连接(如果有)setLogger()
- 好,决定发布完整答案:
Qt添加到C++中,除了其他特征外,信号和时隙的功能也可以用元对象编译器(简称MOC)完成。编译Qt代码时,moc解析头文件并为您创建源代码,这可以在moc文件中看到。有时这些文件会失去同步,清理这些文件将解决此问题
如果更仔细地观察Q_对象宏,它的定义如下:-#define Q_OBJECT \
public: \
Q_OBJECT_CHECK \
static const QMetaObject staticMetaObject; \
virtual const QMetaObject *metaObject() const; \
virtual void *qt_metacast(const char *); \
QT_TR_FUNCTIONS \
virtual int qt_metacall(QMetaObject::Call, int, void **); \
private: \
Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
struct QPrivateSignal {};
如在这里可以看到的,<强> > QObjult宏向类添加函数定义,并在QObjt父类中实现这些功能,这些类提供了附加的C++特性,如信号/时隙、属性、RTTI等。在调用信号和时隙时,内部Qt使用<强> QtyMeta Actual/St>函数。对这些实现有一个有趣的解释。因此,如果从QObject派生的类中没有Q_对象宏,信号和插槽将无法工作。
有人提到需要Q_对象宏,但我认为一点解释也会有用,因为理解为什么需要它有助于记住使用它Qt添加到C++中,除了其他特征外,信号和时隙的功能也可以用元对象编译器(简称MOC)完成。编译Qt代码时,moc解析头文件并为您创建源代码,这可以在moc文件中看到。有时这些文件会失去同步,清理这些文件将解决此问题
如果更仔细地观察Q_对象宏,它的定义如下:-#define Q_OBJECT \
public: \
Q_OBJECT_CHECK \
static const QMetaObject staticMetaObject; \
virtual const QMetaObject *metaObject() const; \
virtual void *qt_metacast(const char *); \
QT_TR_FUNCTIONS \
virtual int qt_metacall(QMetaObject::Call, int, void **); \
private: \
Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
struct QPrivateSignal {};
如在这里可以看到的,<强> >QObjult宏向类添加函数定义,并在QObjor父类中实现这些函数,这些类提供了附加的C++特性,例如信号/时隙、PRPE