19

以下链接中的示例: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,这里出错的原因是什么?

4

5 回答 5

36

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

HEADERS += yourheader.h 

然后重新运行qmake

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

于 2011-05-02T08:14:55.813 回答
23

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

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

moc 编译器在 moc_xxxx.cpp 中生成存根和调用,并生成 vtable 内容

于 2012-12-29T21:35:40.593 回答
1

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

#include <QtGui/QApplication>

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

    w.show();

    return a.exec();
}
于 2011-05-02T08:16:34.673 回答
1

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

#include "moc_stuff.cpp"

(这是 Qt 4.7.0)

于 2012-06-04T16:51:55.027 回答
0

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


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

class MyWidg : public QWidget
{
    Q_OBJECT

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

HEADERS += file.h

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

于 2018-03-06T12:38:03.533 回答