2017-05-27 32 views
0

我的意思是:我們按下按鈕 - >計數器增加,計數器增加 - > QLabel的值被更新。我遇到了奇怪的錯誤,不想做。我不是C++中的啞人,而是QT中的我。這是我的第一個也是最簡單的應用程序。錯誤,看起來如此main.cpp :(。text.startup + 0xd6):未定義的引用`Vtable櫃檯'?

有一些答案(堆棧溢出)建議添加虛擬構造函數。它沒有效果。

我嘗試將信號和插槽重寫爲新的qt5風格,但還有另外一些問題,我懶得修復它們,是(重寫,而不是懶惰:))一種好方法,也許問題真的與版本有關?

我只是沒有嘗試重新安裝QT或安裝Qt4,也許問題在於它?

有關版本:

$ qmake --version 

響應:

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(); 
} 

嘗試運行它:

qmake && make && ./conn 

所以我看到控制檯:

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 

我該怎麼辦?

回答

0

非常感謝!你的回答是充分的,有用的,並且更加明顯。 解決方法是: 1.移動Counter Counter到Counter.h 從這一刻起關於vtable的消息就消失了。出現的message()和counter :: counterChanged(double)有多重定義。第一個定義是我的Counter.cpp(錯誤方式)。第二個是moc_Counter.cpp,由MOC實用程序生成。所以:

2.卸下定義(我的空定義)的信號功能,因爲MOC使得自己在文件moc_Counter.cpp:

// 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); 
} 

而且導致多個定義的問題。

總結起來,工作代碼:

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" 

謝謝你,你太棒了!

+0

不客氣。進一步的建議:如果你使用Qt5,習慣使用新的連接語法,因爲它是類型安全的,並在編譯時檢查:'QObject :: connect(&button1,&QPushButton :: clicked,&counter1,&Counter :: slot_incCounter );'。 – Lorenz

+0

好的,非常感謝。 –

1

Qt使用元對象編譯器(moc)來啓用例如信號和插槽。默認情況下,如果Q_OBJECT宏位於頭文件中,它可以很好地工作。所以最簡單的方法是將Counter放入它自己的頭文件/實現文件中,重新運行qmakemake。 (這是好的做法...)

如果你想堅持一個main.cpp文件,你需要明確地告訴moc該文件包含moc需要解析的宏。爲此,您可以在main.cpp中的最末尾以下行:

#include "main.moc" 

然後重新運行也和qmakemake

請注意,手動包含moc-include指令不是最佳選擇。所以更好地將C++類從一開始分爲單獨的文件...

+0

將其移至.h作品。沒有嘗試第二種方式。謝謝你的完整答案! –

相關問題