错误看起来如此 main.cpp:(.text.startup+0xd6): undefined reference to `vtable for Counter'?
ERROR that looks so main.cpp:(.text.startup+0xd6): undefined reference to `vtable for Counter'?
我的意思是自然而然地有一些微不足道的问题:我们按下按钮 --> 计数器增加,计数器增加 --> QLabel 的值被更新。我发现了奇怪的错误,不想做。我在 C++ 中不是假人,但在 QT 中我是。这是我在其中的第一个也是最微不足道的应用程序。
那里的一些答案(在 Stack Overflow 上)建议添加虚拟构造函数。它没有效果。
我尝试将信号和槽重写为新的 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
我该怎么办?
Qt 使用元对象编译器 (moc) 来启用例如信号和槽。默认情况下,如果 Q_OBJECT 宏位于头文件中,它会完美运行。所以最简单的方法是将 Counter
放入它自己的 header/implementation 文件中,然后重新运行 qmake
和 make
。 (顺便说一下,这是很好的做法...)
如果你想坚持使用单个 main.cpp 文件,你需要明确地告诉 moc 这个文件包含 moc 需要解析的宏。您可以在 main.cpp:
的末尾使用以下行来执行此操作
#include "main.moc"
然后也重新运行 qmake
和 make
。
请记住,手动包含 moc-include 指令不是最佳选择。所以最好从一开始就把你的 C++ 类 分成单独的文件...
非常感谢!您的回答是完整的、有用的并且使一切变得更加明显。
解决方案是:
1。将 class 计数器移动到 Counter.h
从这一刻起,关于 vtable 的消息就消失了。出现goodbye() 和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"
谢谢你,你真棒!
我的意思是自然而然地有一些微不足道的问题:我们按下按钮 --> 计数器增加,计数器增加 --> QLabel 的值被更新。我发现了奇怪的错误,不想做。我在 C++ 中不是假人,但在 QT 中我是。这是我在其中的第一个也是最微不足道的应用程序。
那里的一些答案(在 Stack Overflow 上)建议添加虚拟构造函数。它没有效果。
我尝试将信号和槽重写为新的 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
我该怎么办?
Qt 使用元对象编译器 (moc) 来启用例如信号和槽。默认情况下,如果 Q_OBJECT 宏位于头文件中,它会完美运行。所以最简单的方法是将 Counter
放入它自己的 header/implementation 文件中,然后重新运行 qmake
和 make
。 (顺便说一下,这是很好的做法...)
如果你想坚持使用单个 main.cpp 文件,你需要明确地告诉 moc 这个文件包含 moc 需要解析的宏。您可以在 main.cpp:
的末尾使用以下行来执行此操作#include "main.moc"
然后也重新运行 qmake
和 make
。
请记住,手动包含 moc-include 指令不是最佳选择。所以最好从一开始就把你的 C++ 类 分成单独的文件...
非常感谢!您的回答是完整的、有用的并且使一切变得更加明显。 解决方案是: 1。将 class 计数器移动到 Counter.h 从这一刻起,关于 vtable 的消息就消失了。出现goodbye() 和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"
谢谢你,你真棒!