69

Windows 7 Ultimate 32 ビットで Qt Creator 2.0.1 と Qt 4.7.0 (32 ビット) を使用しています。

エラーを生成するための最小限の次のコードを検討してください。

class T : public QObject, public QGraphicsItem
{
    Q_OBJECT

public:
    T() {}

    QRectF      boundingRect() const {return QRectF();}
    void        paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                      QWidget *widget) {}
};

int main()
{
    T t;
    return 0;
}

上記のコード フラグメントにより、次のリンカ エラーが発生します。

関数 `T' では:

「T の vtable」への未定義の参照

「T の vtable」への未定義の参照

関数 `~T' では:

「T の vtable」への未定義の参照

「T の vtable」への未定義の参照

を含む行をコメントアウトすると、正常にQ_OBJECTコンパイルされます。シグナルとスロットがQGraphicsItem必要なので、 が必要Q_OBJECTです。

コードの何が問題になっていますか? ありがとう。

4

5 に答える 5

135

これは、MOC によって生成されたユニットがリンク処理に含まれていないためです。または、まったく生成されていない可能性があります。最初に行うことは、クラス宣言を別のヘッダー ファイルに入れることです。ビルド システムが実装ファイルをスキャンしていない可能性があります。

もう 1 つの可能性は、問題のクラスが Qt メタ オブジェクト システムに属していなかったことです (つまり、Q_OBJECT がなかったか、QObject からまったく継承されていなかった可能性があります)。 MOCに必要なルール。qmake を強制的に実行する最も簡単な方法は、空白を追加してから削除するなど、プロジェクト ファイルに重要でない変更を加えてタイムスタンプを更新することです。または、Qt Creator を使用している場合は、プロジェクトのコンテキスト メニューから [Run qmake] を選択します。

于 2011-01-23T14:33:58.050 に答える
26

ソースファイルでサブクラスを定義したい場合はQObject、次の行を追加する必要があります

#include "file.moc"

ソースファイルの名前がfile.cppであるクラス定義の後のある時点で。qmakeもちろん、実行する適切なルールがmocMakefile に追加されるように、再実行する必要があります。

ヘッダー ファイルにある場合にのみQ_OBJECT、クラス定義に が存在mocするために呼び出されます。ソースファイルの場合、強制的mocに使用するにはこの余分な行が必要です。

以前にも同様の質問があったと思いますが、見つけられませんでした。

于 2011-01-23T15:45:14.973 に答える
8

Q_OBJECTクラスを別々のファイルに入れます。これは、クラスごとに1つの.hと1つの.cppです。Qtのメタオブジェクトマクロは、この点でちょっと厄介です。

また、目的に応じてQGraphicsObjectを使用できます。そこで時間を節約できます。

編集:あなたはクリエイターを使用しているようです。新しいファイルまたはプロジェクトでその新しいC++クラス関数を使用して、「正しい方法」でファイルを作成します:)

于 2011-01-23T15:18:02.080 に答える
6

これは、他の質問で提供されたすべての修正が追加された作業コードです(クリーンコンパイルを試み、これらの修正が役立ちます):

#include <QGraphicsItem>

class T : public QObject, public QGraphicsItem
{
    Q_OBJECT
    Q_INTERFACES(QGraphicsItem) //Required.

public:
    T() {}
    QRectF      boundingRect() const {return QRectF();}
    void        paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                      QWidget *widget) {}
};

int main(int argc, char *argv[])
{
    T *t = new T;
    return 0;
}

#include "main.moc" // Required.

Troubadour と serge_gubenko の功績

于 2011-01-23T21:14:26.970 に答える
4

見るべきことがいくつかあります:

  1. pro ファイルに QT += gui を追加します
  2. ヘッダーファイルのみで QObject 派生クラスを定義していることを確認してください (編集: Troubadour が指摘したように、これは必須ではありません)。
  3. T クラスの宣言に Q_INTERFACES(QGraphicsItem) を追加します。

以下に例を示します。

目:

class T : public QObject, public QGraphicsItem
{
    Q_OBJECT
    Q_INTERFACES(QGraphicsItem)

public:
    T();
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
};

t.cpp:

T::T() {}

QRectF T::boundingRect() const
{
    return QRectF();
}

void T::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(painter);
    Q_UNUSED(option);
    Q_UNUSED(widget);
}

上記のコードをコンパイルしてみましたが、問題はありませんでした。

これが役に立てば幸いです、よろしく

于 2011-01-23T15:45:12.943 に答える