2017-05-27 1 views
0

Ich habe natürlich triviale Frage wie ich meine: wir drücken Knopf -> Zähler erhöht, Zähler erhöht -> QLabels Wert wird erneuert. Ich habe merkwürdigen Fehler gefangen und will nicht tun. Ich bin kein Dummy in C++, aber in QT bin ich. Es ist meine erste und trivialste Anwendung darin.Fehler, der so aussieht main.cpp :(. Text.startup + 0xd6): undefinierter Verweis auf `vtable for Counter '?

Einige Antworten dort (auf Stack Overflow) empfohlen, virtuellen Konstruktor hinzuzufügen. Es hat keine Wirkung.

Ich habe versucht, Signale und Slots neu zu qt5 Stil zu schreiben, aber es gab ein anderes Problem, ich war zu faul, sie zu beheben, war es (Neuschreiben, nicht Faulheit :)) ein guter Weg, vielleicht ist das Problem wirklich mit Versionen?

Ich habe gerade nicht versucht, QT neu zu installieren oder Qt4 zu installieren, vielleicht ist das Problem drin?

Versionen:

$ qmake --version 

antwortet:

QMake version 3.0 
Using Qt version 5.5.1 in /usr/lib/x86_64-linux-gnu 

conn.pro:

TEMPLATE = app 

QT += core gui 

TARGET = conn 
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 

SOURCES += main.cpp 

main.cpp:

#include <QApplication> 
#include <QLabel> 
#include <QPushButton> 
#include <QObject> 

class Counter : public QObject { 
    Q_OBJECT 

private: 
    double i_; 

public: 
    virtual ~Counter() 
    { 

    } 
    Counter() : QObject(), i_(0) 
    { 
    } 


public slots: 
    void slot_incCounter(); 

signals: 
    void goodbye(){} 
    void counterChanged(double){} 
}; 

void Counter::slot_incCounter() { 
    emit counterChanged(++i_); 
    if (i_ == 5) { 
     emit goodbye(); 
    } 
} 

int main(int argc, char* argv[]) { 
    QApplication my_app(argc, argv); 

    QLabel label1("label i created"); 
    label1.show(); 

    QPushButton button1("press me"); 
    button1.show(); 

    Counter counter1; 

    QObject::connect(&button1, SIGNAL(clicked()), 
        &counter1, SLOT(slot_incCounter())); 

    QObject::connect(&counter1, SIGNAL(counterChanged(double a)), 
        &label1, SLOT(setNum(double a))); 

    QObject::connect(&counter1, SIGNAL(goodbye()), 
        &my_app, SLOT(quit())); 

    return my_app.exec(); 
} 

versuchen, sie auszuführen:

qmake && make && ./conn 

So sehe ich in der Konsole:

g++ -m64 -Wl,-O1 -o conn main.o -L/usr/X11R6/lib64 -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread 
main.o: In function `main': 
main.cpp:(.text.startup+0xd6): undefined reference to `vtable for Counter' 
collect2: error: ld returned 1 exit status 
Makefile:144: recipe for target 'conn' failed 
make`:` *** [conn] Error 1 

Was soll ich tun?

Antwort

0

Vielen Dank! Deine Antwort war voll, nützlich und alles offensichtlicher. Lösung war: 1. Verschieben Klasse Zähler zu Counter.h Seit diesem Zeitpunkt die Nachricht über VTable verschwunden. Es erschienen Meldungen, dass auf Wiedersehen() und Counter :: counterChanged (double) mehrere Definitionen haben. Die erste Definition war meine in Counter.cpp (WRONG WAY). Die zweite war in moc_Counter.cpp, generiert von MOC-Dienstprogramm.Also:

2. Entfernen Definitionen (meine leeren Definitionen) von Signalfunktionen, weil moc seine eigene in der Datei moc_Counter.cpp macht:

// SIGNAL 0 
void Counter::goodbye() 
{ 
    QMetaObject::activate(this, &staticMetaObject, 0, Q_NULLPTR); 
} 

// SIGNAL 1 
void Counter::counterChanged(double _t1) 
{ 
    void *_a[] = { Q_NULLPTR, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) }; 
    QMetaObject::activate(this, &staticMetaObject, 1, _a); 
} 

und sie verursachen ein Problem mehrfacher Definition.

es zusammenfassend, Arbeitscode:

main.cpp:

#include <QApplication> 
#include "Counter.h" 



int main(int argc, char* argv[]) { 
    QApplication my_app(argc, argv); 

    QLabel label1("1"); 
    label1.show(); 

    QPushButton button1("press me"); 
    button1.show(); 

    Counter counter1; 

    QObject::connect(&button1, SIGNAL(clicked()), 
        &counter1, SLOT(slot_incCounter())); 

    QObject::connect(&counter1, SIGNAL(counterChanged(double)), 
        &label1, SLOT(setNum(double))); 

    QObject::connect(&counter1, SIGNAL(goodbye()), 
        &my_app, SLOT(quit())); 

    return my_app.exec(); 
} 


void Counter::slot_incCounter() { 
    emit counterChanged(++i_); 
    if (i_ == 5) { 
     emit goodbye(); 
    } 
} 

Counter.h:

#ifndef COUNTER_H 
#define COUNTER_H 

#include <QLabel> 
#include <QPushButton> 
#include <QObject> 

class Counter : public QObject { 
    Q_OBJECT 
private: 
    double i_; 

public: 
    virtual ~Counter() 
    { 
    } 

    Counter() : QObject() 
    { 
    } 


public slots: 
    void slot_incCounter(); 

signals: 
    void goodbye(); 
    void counterChanged(double); 
}; 

#endif // COUNTER_H 

Counter.cpp:

#include "Counter.h" 

Danke, du bist großartig!

+0

Gern geschehen. Ein weiterer Hinweis: Wenn Sie Qt5 verwenden, verwenden Sie die neue Verbindungssyntax, da sie typsicher ist und zur Kompilierzeit überprüft wird: 'QObject :: connect (& button1, & QPushButton :: clicked, & counter1, & Counter :: slot_incCounter); '. – Lorenz

+0

ok, vielen Dank. –

1

Qt verwendet den Metaobjekt-Compiler (moc), um z. Signal und Schlitze. Standardmäßig funktioniert es perfekt, wenn das Makro Q_OBJECT in einer Header-Datei ist. Am einfachsten wäre es also, wenn Sie Counter in seine eigene Header-/Implementierungsdatei schreiben, dann wiederholen Sie qmake und make. (Das ist übrigens gute Praxis ...)

Wenn Sie mit einer einzigen main.cpp Datei bleiben wollen, müssen Sie dem Moc explizit mitteilen, dass diese Datei Makros enthält, die moc analysieren muss. Sie tun dies mit der folgenden Zeile am Ende von main.cpp:

#include "main.moc" 

auch qmake und make dann erneut ausführen.

Bitte beachten Sie, dass die manuelle Einbeziehung einer moc-include-Direktive nicht die beste Wahl ist. Also teilen Sie Ihre C++ Klassen gleich von Anfang an in separate Dateien ...

+0

Verschieben Sie es auf die .h funktioniert. Ich habe es nicht auf dem zweiten Weg versucht. Vielen Dank für Ihre vollständige Antwort! –

Verwandte Themen