web-dev-qa-db-fra.com

Qt: Signaux et slots Erreur: référence indéfinie à `vtable pour

Exemple suivant tiré de ce lien: http://developer.kde.org/documentation/books/kde-2.0-development/ch03lev1sec3.html

#include <QObject>
#include <QPushButton>
#include <iostream>
using namespace std;

class MyWindow : public QWidget
{
    Q_OBJECT  // Enable slots and signals
    public:
        MyWindow();
    private slots:
        void slotButton1();
        void slotButton2();
        void slotButtons();
    private:
        QPushButton *button1;
        QPushButton *button2;
};

MyWindow :: MyWindow() : QWidget()
{
    // Create button1 and connect button1->clicked() to this->slotButton1()
    button1 = new QPushButton("Button1", this);
    button1->setGeometry(10,10,100,40);
    button1->show();
    connect(button1, SIGNAL(clicked()), this, SLOT(slotButton1()));

    // Create button2 and connect button2->clicked() to this->slotButton2()
    button2 = new QPushButton("Button2", this);
    button2->setGeometry(110,10,100,40);
    button2->show();
    connect(button2, SIGNAL(clicked()), this, SLOT(slotButton2()));

    // When any button is clicked, call this->slotButtons()
    connect(button1, SIGNAL(clicked()), this, SLOT(slotButtons()));
    connect(button2, SIGNAL(clicked()), this, SLOT(slotButtons()));
}

// This slot is called when button1 is clicked.
void MyWindow::slotButton1()
{
    cout << "Button1 was clicked" << endl;
}

// This slot is called when button2 is clicked
void MyWindow::slotButton2()
{
    cout << "Button2 was clicked" << endl;
}

// This slot is called when any of the buttons were clicked
void MyWindow::slotButtons()
{
    cout << "A button was clicked" << endl;
}

int main ()
{
    MyWindow a;
}

résulte en:

    [13:14:34 Mon May 02] ~/junkPrograms/src/nonsense  $make
g++ -c -m64 -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/opt/qtsdk-2010.05/qt/mkspecs/linux-g++-64 -I. -I/opt/qtsdk-2010.05/qt/include/QtCore -I/opt/qtsdk-2010.05/qt/include/QtGui -I/opt/qtsdk-2010.05/qt/include -I. -I. -o signalsSlots.o signalsSlots.cpp
g++ -m64 -Wl,-O1 -Wl,-rpath,/opt/qtsdk-2010.05/qt/lib -o nonsense signalsSlots.o    -L/opt/qtsdk-2010.05/qt/lib -lQtGui -L/opt/qtsdk-2010.05/qt/lib -L/usr/X11R6/lib64 -lQtCore -lpthread
signalsSlots.o: In function `MyWindow::MyWindow()':
signalsSlots.cpp:(.text+0x1a2): undefined reference to `vtable for MyWindow'
signalsSlots.cpp:(.text+0x1aa): undefined reference to `vtable for MyWindow'
signalsSlots.o: In function `MyWindow::MyWindow()':
signalsSlots.cpp:(.text+0x3e2): undefined reference to `vtable for MyWindow'
signalsSlots.cpp:(.text+0x3ea): undefined reference to `vtable for MyWindow'
signalsSlots.o: In function `main':
signalsSlots.cpp:(.text+0x614): undefined reference to `vtable for MyWindow'
signalsSlots.o:signalsSlots.cpp:(.text+0x61d): more undefined references to `vtable for MyWindow' follow
collect2: ld returned 1 exit status
make: *** [nonsense] Error 1

vtable est pour les fonctions virtuelles, autant que je sache, quelle est la raison de l'erreur ici?

19
Aquarius_Girl

Il semble que moc ne génère pas de code pour votre QObject car vous le déclarez dans le fichier .cpp. Le moyen le plus simple de résoudre ce problème consiste à déplacer la déclaration de MyWindow dans un en-tête et à ajouter l'en-tête à la liste HEADERS dans le fichier .pro :

HEADERS += yourheader.h 

Puis relancez qmake.

(Veuillez noter que le livre KDE 2.0 que vous regardez est bien dépassé)

37
Frank Osterfeld

Peut-être trop tard, mais… nous avions le même problème et nous nous sommes battus pendant un certain temps pour trouver d'où il vient.

Faites un clic droit sur votre projet et sélectionnez «Exécuter qmake» pour obtenir une nouvelle version des classes MOC. Il fonctionne généralement automatiquement ...

Le compilateur moc génère les stubs et les appels dans moc_xxxx.cpp et génère les commandes vtable.

23
sylvain

Basé sur le commentaire andref juste ci-dessus, lorsque tout est dans un fichier cpp comme stuff.cpp, vous devez ajouter à la fin du fichier:

#include "moc_stuff.cpp"

(c'est avec Qt 4.7.0)

1
calandoa

Il suffit de changer votre main () comme suit:

#include <QtGui/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyWindow w;

    w.show();

    return a.exec();
}
1
anj

Ce problème peut être causé par l'une des raisons suivantes. Je les ai tous rencontrés de temps en temps.


La macro Q_OBJECT est peut-être absente de votre en-tête de classe. Ajoutez la macro à l'en-tête comme déjà noté par d'autres réponses.

class MyWidg : public QWidget
{
    Q_OBJECT

Votre en-tête de classe ne peut pas être analysé par le moc. Ajoutez le fichier d'en-tête dans les définitions HEADERS de votre fichier de projet .pro (ou .pri).

HEADERS += file.h

Si rien de ce qui précède n'est vrai, vous devrez probablement réexécuter qmake pour vous assurer que moc analyse à nouveau l'en-tête, juste au cas où la macro Q_OBJECT serait ajoutée à l'en-tête après l'exécution de qmake. Il suffit de lancer à nouveau qmake.

0
kotsos