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)));
}

或者在初始化记录器后连接该信号。

好,决定发布完整答案:

  • 首先,您确实需要
    Q_对象
    宏。当您从QtCreator的
    Build
    菜单中执行
    Clean All
    运行qmake
    Rebuild All
    时,从中获得的错误可能会消失。Qt依赖于大量生成的样板代码,您永远不必键入这些代码,如果没有
    Q_OBJECT
    ,则不会生成这些代码。这就是为什么您有时需要在进行更改后进行清理,运行qmake(生成代码)并使用现在最新生成的代码进行重建

  • 第二个-在
    applicationManagement
    的构造函数中,连接到未初始化的指针记录器。这可能就是为什么会出现分段错误。您可以使用两种方法来解决此问题:

  • 将指针传递到
    applicationManagement
    的构造函数中的记录器,这样您就可以在构造函数中连接到某个对象。这样,除非在构造函数初始化列表中使用
    logger(新的QXmppLogger)
    ,否则无法在记录器之前实例化
    applicationManagement

  • 将连接从
    applicationManagement
    构造函数移动到
    setLogger()
    方法。不要忘记断开以前的连接(如果有)


    • 好,决定发布完整答案:

      • 首先,您确实需要
        Q_对象
        宏。当您从QtCreator的
        Build
        菜单中执行
        Clean All
        运行qmake
        Rebuild All
        时,从中获得的错误可能会消失。Qt依赖于大量生成的样板代码,您永远不必键入这些代码,如果没有
        Q_OBJECT
        ,则不会生成这些代码。这就是为什么您有时需要在进行更改后进行清理,运行qmake(生成代码)并使用现在最新生成的代码进行重建

      • 第二个-在
        applicationManagement
        的构造函数中,连接到未初始化的指针记录器。这可能就是为什么会出现分段错误。您可以使用两种方法来解决此问题:

      • 将指针传递到
        applicationManagement
        的构造函数中的记录器,这样您就可以在构造函数中连接到某个对象。这样,除非在构造函数初始化列表中使用
        logger(新的QXmppLogger)
        ,否则无法在记录器之前实例化
        applicationManagement

      • 将连接从
        applicationManagement
        构造函数移动到
        setLogger()
        方法。不要忘记断开以前的连接(如果有)


      有人提到需要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宏向类添加函数定义,并在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