【问题标题】:Qt: Signals and slots Error: undefined reference to `vtable forQt:信号和槽错误:未定义的对`vtable的引用
【发布时间】:2011-08-16 19:30:00
【问题描述】:

以下链接中的示例: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;
}

结果:

    [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 用于虚函数,AFAIK,这里出错的原因是什么?

【问题讨论】:

标签: qt signals-slots vtable undefined-reference


【解决方案1】:

看起来 moc 没有为您的 QObject 生成代码,因为您在 .cpp 文件中声明了它。解决此问题的最简单方法是将 MyWindow 的声明移动到标题中,并将标题添加到 .pro 文件中的 HEADERS 列表中:

HEADERS += yourheader.h 

然后重新运行qmake

(请注意,您看到的 KDE 2.0 书籍已经过时了)

【讨论】:

  • 感谢您的回复,但是我没有办法将声明和定义保留在 .cpp 文件中吗?
  • 试试 HEADERS += your.cpp 。通常,尽管可能,但我发现 QObject 声明非常痛苦,以至于我更喜欢​​使用它们(私有)标头。它适用于所有构建系统,无论是 qmake,cmake,...
  • 再次感谢,我将 .h、.cpp 和 main :mad: 分开了,它解决了错误,我还没有研究有关 moc 文件的详细信息。
  • 当你在 filename.cpp 文件中声明一个 QObject 时,你应该在你的 .cpp 文件的末尾添加 #include "filename.moc" 并且 qmake 会为你做正确的事情。例如,这是 KDE 中的常见做法。
  • 优秀的答案。 Qt 对 C++ 本身施加了额外的限制,这很烦人,但我想我可以忍受。
【解决方案2】:

也许为时已晚,但是...遇到了同样的问题,并为找到它的来源而奋斗了一段时间。

右键单击您的项目并选择“运行 qmake”以新建 MOC 类。它通常会自动运行...

moc 编译器在 moc_xxxx.cpp 中生成存根和调用,并生成 vtable 的东西

【讨论】:

  • 我不使用 qtcreator。在问这里之前,我确实运行了 qmake 很多次。它没有帮助。
  • @AnishaKaul 同样。为我运行 qmake 并不能解决任何问题。如果我运行qmake --project,那么它会重新生成.pro,我可以编译,但这会影响人们对.pro所做的所有更改,这真的很糟糕。
  • 1++ 这个解决了我的问题
  • 也解决了我的问题!!谢谢+1
  • 将 Q_OBJECT 添加到 .h 文件并运行 qmake 后,它工作了 +1
【解决方案3】:

只需将您的 Main() 更改如下:

#include <QtGui/QApplication>

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

    w.show();

    return a.exec();
}

【讨论】:

    【解决方案4】:

    根据上面的andref注释,当所有内容都在一个cpp文件中时,例如stuff.cpp,您需要在文件末尾添加:

    #include "moc_stuff.cpp"
    

    (这是 Qt 4.7.0)

    【讨论】:

    • 使用 Qt 4.8,这对我不起作用。我必须按照提到的评论建议去做。
    【解决方案5】:

    此问题可能是由以下某些原因引起的。我不时偶然发现所有这些。


    您的类标头可能缺少 Q_OBJECT 宏。如其他答案所述,将宏添加到标题中。

    class MyWidg : public QWidget
    {
        Q_OBJECT
    

    moc 可能无法解析您的类标头。在 .pro(或 .pri)项目文件的 HEADERS 定义中添加头文件。

    HEADERS += file.h
    

    如果以上都不是,那么您可能需要再次运行 qmake 以确保 moc 再次解析标头,以防在 qmake 运行后将 Q_OBJECT 宏添加到标头中。再次运行 qmake。

    【讨论】:

      猜你喜欢
      • 2014-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-30
      • 2011-02-03
      • 1970-01-01
      相关资源
      最近更新 更多