0

applicationManagerQXmppLogger クラス オブジェクトによってそれを消費するメッセージをログに記録することを想定している一方で、情報メッセージまたはエラーが発生したときにシグナルを発するクラスがあります。のようなメソッドを取得し、内部 QXmppLoggerのシグナルinfo()warning()発するQXmppLoggable クラスがあります。logmessage()したがって、シグナルを発行するために、QObject自体を継承するQXmppLogableクラスを継承したため、発行されたSIGNAL()をinfo()およびwarning()メソッドで使用および接続して、QXmppLoggerオブジェクトのSLOT(info())に接続できます。コード スニペットは次のとおりです。warning()logmessage()log()

ヘッダ"imApplicationManager.h"

class applicationManagement: public QXmppLoggable
{
    //Q_OBJECT
public:
    bool createDataBaseConnection();
    applicationManagement();
    ~applicationManagement();
    void setLogger(QXmppLogger *logger);
private:
    QXmppLogger *logger;
};

および関連"imApplicationManager.cpp"

applicationManagement::applicationManagement()
{
   QObject::connect(this, SIGNAL(logMessage(QXmppLogger::MessageType,QString)),
                    logger, SLOT(log(QXmppLogger::MessageType,QString)));
}

applicationManagement::~applicationManagement()
{
    // db..closing
}

bool applicationManagement::createDataBaseConnection(){

    //...database conncetion...

    if (!dataBase.open()){
        warning(QString("Cannot open database %1").arg(dataBase.lastError().text()));
        qDebug()<< "Cannot open database " << dataBase.lastError();
      return false;
    }
    info(QString("Database succeeded!"));
  return true;
}

void applicationManagement::setLogger(QXmppLogger *logger)
{
    if(this->logger != logger)
        this->logger = logger;
}

の中にmain.cpp

#include "imApplicationManager"
#incLude "QXmppLogger"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    applicationManagement aa;

    QXmppLogger log;

    aa.setLogger(&log);   

    return a.exec();
}

コンパイルではエラーは通知されませんが、起動するとシグメンテーション エラーが発生します。どうすれば修正できますか?

4

3 に答える 3

3

OK、完全な回答を投稿することにしました:

  • まず、Q_OBJECTマクロが必要です。そこから得られるエラーは、QtCreator のメニューから削除すると消える可能性Clean AllがありますRun qmake。Qt は、入力する必要のない大量の定型コードに依存しており、そのコードがなければコードは生成されません。これが、変更を行った後にクリーンアップし、qmake (コードを生成する) を実行し、生成された最新のコードで再構築する必要がある場合がある理由です。Rebuild AllBuildQ_OBJECT

  • 2 番目 - コンストラクターでapplicationManagement、初期化されていないポインター ロガーに接続します。これがおそらく、セグメンテーション違反が発生する理由です。これを修正するには、次の 2 つの方法を使用できます。

    1. のコンストラクターでロガーへのポインターを渡しますapplicationManagement。このようにして、コンストラクターで接続するものがあります。この方法では、コンストラクターの初期化リストでapplicationManagement使用しない限り、ロガーの前にインスタンス化できません。logger(new QXmppLogger)

    2. 接続をapplicationManagementコンストラクターからsetLogger()メソッドに移動します。もしあれば、以前の接続を切断することを忘れないでください。

于 2013-08-20T09:34:19.670 に答える
2

Q_OBJECT マクロが必要であると述べられていますが、なぜそれが必要なのかを理解することは、それを使用することを覚えておくのに役立つので、少し説明も役立つと思います.

Qt は、シグナルとスロットの機能を他の機能の中で C++ に追加します。これは、Meta-Object Compiler (略して moc) で行われます。Qt コードをコンパイルするとき、moc はヘッダー ファイルを解析し、moc ファイルで確認できるソース コードを作成します。時折、これらは同期しなくなり、これらのファイルをクリーニングすると、この問題が修正されます。

Q_OBJECT マクロを詳しく見ると、次のように定義されています。

#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 {};

ここに見られるように、Q_OBJECTマクロは関数定義をクラスに追加し、シグナル/スロット、プロパティ、RTTI などの追加された C++ 機能を提供する QObject 親クラスでこれらの実装を追加します。シグナルとスロットを内部的に呼び出すときQt はqt_metacall関数を使用します。これらの実装に関する興味深い説明がここにあります。したがって、QObject から派生したクラスに Q_OBJECT マクロがないと、シグナルとスロットは機能しません。

于 2013-08-20T10:39:32.840 に答える