.cppファイルにq_objectマクロがある場合、なぜ私のプロジェクトがリンクしないのですか?

StackOverflow https://stackoverflow.com/questions/8307059

  •  25-10-2019
  •  | 
  •  

質問

このコードは、意図したとおりにコンパイル、リンク、および動作します。

#include <QApplication>
#include <QListView>
#include "File_List_Model.h"

int main(int c,char**v)
{
    QApplication app(c,v);
    QStringList list;

    list << "a" << "b" << "c";

    File_List_Model* model = new File_List_Model;
    model->set_entries(list);

    QListView* view = new QListView;
    view->setModel(model);
    view->show();

    return app.exec();
} 

しかし、クラスの定義を置いたとき .cpp ヘッダーファイルの代わりにファイルで、それを示すリンカーエラーが表示されます vtable 適切に定義されていませんでした。

#include <QApplication>
#include <QListView>
//#include "File_List_Model.h"
#include "File_List_Proxy.h"
#include <QAbstractItemModel>
#include <QStringList>

class File_List_Model : public QAbstractItemModel
{
    Q_OBJECT
private:
    QStringList data_;
public:
    File_List_Model(QObject *parent = 0) :
        QAbstractItemModel(parent)
    {
    }

    int columnCount(const QModelIndex& parent) const
    {
        return 1;
    }

    QVariant data(const QModelIndex & index, int role) const
    {
        switch(role)
        {
            case Qt::DisplayRole:
            return data_[index.row()];
        default:
            return QVariant();
        }
    }

     QModelIndex index(int row, int column, const QModelIndex & parent) const
    {
        return createIndex(row,column);
    }

    QModelIndex parent(const QModelIndex & index) const
    {
        return QModelIndex();
    }

     bool set_entries(const QStringList& entries)
     {
         if (entries.size())
         {
         beginInsertRows(createIndex(0,0),0,entries.size());
         data_ = entries;
         endInsertRows();
         emit dataChanged(createIndex(0,0),createIndex(0,entries.size()));
         return true;
         }
         else
         {
             return false;
         }
     }

     int rowCount(const QModelIndex & parent) const
     {
         return data_.size();
     }


};

int main(int c,char**v)
{
    QApplication app(c,v);
    QStringList list;

    list << "a" << "b" << "c";

    File_List_Model* model = new File_List_Model;
    model->set_entries(list);

    File_List_Proxy* proxy = new File_List_Proxy;
    proxy->setSourceModel(model);

    QListView* view = new QListView;
    view->setModel(proxy);
    view->show();

    return app.exec();
}
//error:   
debug/moc_File_List_Model.o:moc_File_List_Model.cpp:(.rdata$_ZTV15File_List_Model[vtable for File_List_Model]+0x44): undefined reference to `File_List_Model::columnCount(QModelIndex const&) const'
debug/moc_File_List_Model.o:moc_File_List_Model.cpp:(.rdata$_ZTV15File_List_Model[vtable for File_List_Model]+0x4c): undefined reference to `File_List_Model::data(QModelIndex const&, int) const'

これはまったく同じコードのようです。コードがヘッダーに含まれていて、それ以外の場合はリンクしないのに、なぜリンクするのですか?

役に立ちましたか?

解決

QTは使用します moc たとえば、信号スロットメカニズムに必要なC ++拡張機能を処理するツール。このツールは、プロジェクト内のすべてのヘッダー(!)ファイルを処理し、それらのクラスを含むメタオブジェクトコードを含む新しいソースファイルを生成します Q_OBJECT 大きい。

クラスが定義されている場合 .cpp の代わりにファイル .h ファイル moc 適切に処理できません。

見て この記事 QT Meta-Objectコンパイラの詳細については。

他のヒント

QTはヘッダーファイルでMOCを実行し、ソースで実行しないためです。

リンカーは、MOC出力のコンパイルから生じるオブジェクトコードの欠落について不平を言っています。これは、MOCがソースファイルを処理したが、その出力がオブジェクトファイルにコンパイルされていないためです。

ヘッダーファイルの場合、ビルドシステムは、複数の翻訳ユニットに含めることを目的としており、 1つの定義ルール. 。したがって、MOC出力にはヘッダーファイルを含めることができ、スタンドアロンの翻訳ユニットとしてコンパイルされます。

しかし、あなたが持っているなら Q_OBJECT a内のマクロ .cpp ファイル、MOC出力は単独でコンパイルできません:それはあなたからの宣言にアクセスできません .cpp ファイルするので、コンパイルできません!また、あなたを含めることはできません .cpp ファイルは、それが違反するためです 1つの定義ルール: :2つの翻訳ユニット - MOC出力とあなた .cpp ファイル - 同じものを定義します。

代わりに、MOCの出力を終了に追加する必要があります .cpp ファイル。たとえば、持っている場合 O_OBJECTmain.cpp, 、 追加 #include "main.moc" ファイルの最後に:

// main.cpp
#include <QtCore>

struct Object : QObject {
  Q_OBJECT
};

int main() {
  Object o;
  qDebug() << o.metaObject()->className();
}

#include "main.moc"
// "main.moc" depends on the declaration of Object above!

上記は次のとおりです sscce.

おそらくqmake/cmakeがビルドをセットアップして、MOC出力が自動的に追加されるようにする必要があると主張することができます。 .cpp コンパイラに送信される前にファイル。これまでのところ、その機能は実装されていません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top