Q_OBJECT 导致“未定义的 v_table 引用”问题
Posted
技术标签:
【中文标题】Q_OBJECT 导致“未定义的 v_table 引用”问题【英文标题】:Q_OBJECT causing a 'undefined reference to v_table' issue 【发布时间】:2014-09-29 08:05:25 【问题描述】:我已经在 Eclipse 中使用 Qt
在 C++
中成功创建了一个 GUI,但是在分配我自己的按钮单击事件时,我被告知宏 Q_OBJECT
需要包含在我的QWidget
班级。
运行时,窗口不再显示,我的QWidget
类的构造函数和析构函数都出现错误。
头文件如下:
#ifndef MEDIAPLAYERWIZARD_H_
#define MEDIAPLAYERWIZARD_H_
#include "../MediaPlayer.Helpers/SystemConfiguration.h"
#include "../MediaPlayer.Helpers/StringHelpers.h"
#include "../MediaPlayer.DataAccess/DataRepository.h"
#include "../MediaPlayer.Helpers/Globals.h"
#include <QtGui/QApplication>
#include <QtGui/QLabel>
#include <QtGui>
#include <QtCore>
#include <sstream>
#include <iostream>
class MediaPlayerWizard: public QWidget
Q_OBJECT
public:
MediaPlayerWizard(QWidget *parent = 0);
void Initialize();
virtual ~MediaPlayerWizard();
private:
QLabel *lblWelcomeMessage;
//Input
QLineEdit *txtName;
QLabel *lblName;
QLineEdit *txtActivationCode;
QLabel *lblActivationCode;
//Buttons
QPushButton *btnActivate;
QPushButton *btnCancel;
//Layouts
QVBoxLayout *fldWizardLayout;
QHBoxLayout *fldWelcomeMessage;
QHBoxLayout *fldName;
QHBoxLayout *fldActivationCode;
QHBoxLayout *fldButtons;
private slots:
void btnActivateClicked();
;
#endif /* MEDIAPLAYERWIZARD_H_ */
而构造函数和析构函数如下:
MediaPlayerWizard::MediaPlayerWizard(QWidget *parent):QWidget(parent)
Initialize(); //Instantiates the buttons and labels etc..
MediaPlayerWizard::~MediaPlayerWizard()
我的所有头文件都列在我的 .pro 文件的 HEADERS
列表中,并且在将 Q_OBJECT
宏添加到我的头文件后,我运行了 QMake
。
初始化代码:
void MediaPlayerWizard::Initialize()
//Widget Configuration
this->setWindowTitle("Media Player: First Run Wizard");
int labelWidth = 150;
//Welcome Message
lblWelcomeMessage = new QLabel;
lblWelcomeMessage->setText("Welcome to the first run wizard that will assist you in\n connecting and registering this advertising player to your account.");
lblWelcomeMessage->setAlignment(Qt::AlignCenter);
//Input Labels
lblName = new QLabel;
lblName->setText("Name: ");
lblName->setFixedWidth(labelWidth);
lblActivationCode = new QLabel;
lblActivationCode->setText("Application Code: ");
lblActivationCode->setFixedWidth(labelWidth);
//Input Fields
txtName = new QLineEdit();
txtActivationCode = new QLineEdit();
//Buttons
btnActivate = new QPushButton;
btnActivate->setText("Activate");
btnCancel = new QPushButton;
btnCancel->setText("Cancel");
//Button Events
QObject::connect(btnActivate, SIGNAL(clicked()), this, SLOT(btnActivateClicked()));
QObject::connect(btnCancel, SIGNAL(clicked()), qApp, SLOT(quit()));
//Layouts
fldWelcomeMessage = new QHBoxLayout;
fldWelcomeMessage->addWidget(lblWelcomeMessage);
fldName = new QHBoxLayout;
fldName->addWidget(lblName);
fldName->addWidget(txtName);
fldActivationCode = new QHBoxLayout;
fldActivationCode->addWidget(lblActivationCode);
fldActivationCode->addWidget(txtActivationCode);
fldButtons = new QHBoxLayout;
fldButtons->addWidget(btnActivate);
fldButtons->addWidget(btnCancel);
fldWizardLayout = new QVBoxLayout;
fldWizardLayout->addLayout(fldWelcomeMessage);
fldWizardLayout->addLayout(fldName);
fldWizardLayout->addLayout(fldActivationCode);
fldWizardLayout->addLayout(fldButtons);
setLayout(fldWizardLayout);
show();
这是显示的错误消息:
Building target: MediaPlayerCPP
Invoking: Cross G++ Linker
g++ -L/usr/lib -o "MediaPlayerCPP" ./src/MediaPlayer.o ./src/MediaPlayerWizard.o ./src/mysqlapidemo.o ./MediaPlayer.Services/MediaPlayerClient.o ./MediaPlayer.Helpers/DeviceManagement.o ./MediaPlayer.Helpers/Globals.o ./MediaPlayer.Helpers/MD5.o ./MediaPlayer.Helpers/StringHelpers.o ./MediaPlayer.Helpers/SystemConfiguration.o ./MediaPlayer.DataAccess/DataObject.o ./MediaPlayer.DataAccess/Database.o ./MediaPlayer.DataAccess/Media.o ./MediaPlayer.DataAccess/MediaLog.o ./MediaPlayer.DataAccess/MediaLogProvider.o ./MediaPlayer.DataAccess/MediaProvider.o ./MediaPlayer.DataAccess/MediaSchedule.o ./MediaPlayer.DataAccess/MediaScheduleProvider.o ./MediaPlayer.DataAccess/SystemConfig.o ./MediaPlayer.DataAccess/SystemConfigProvider.o -lQtCore -lmysqlclient -lz -lQtGui
./src/MediaPlayerWizard.o: In function `MediaPlayerWizard::MediaPlayerWizard(QWidget*)':
/home/gtteam/Projects/MediaPlayerCPP/Debug/../src/MediaPlayerWizard.cpp:10: undefined reference to `vtable for MediaPlayerWizard'
/home/gtteam/Projects/MediaPlayerCPP/Debug/../src/MediaPlayerWizard.cpp:10: undefined reference to `vtable for MediaPlayerWizard'
./src/MediaPlayerWizard.o: In function `MediaPlayerWizard::~MediaPlayerWizard()':
/home/gtteam/Projects/MediaPlayerCPP/Debug/../src/MediaPlayerWizard.cpp:77: undefined reference to `vtable for MediaPlayerWizard'
/home/gtteam/Projects/MediaPlayerCPP/Debug/../src/MediaPlayerWizard.cpp:77: undefined reference to `vtable for MediaPlayerWizard'
collect2: error: ld returned 1 exit status
make: *** [MediaPlayerCPP] Error 1
【问题讨论】:
请同时显示Initialize()
函数的代码。
运行时还是编译时?无论如何清理你的构建目录,添加宏并再次构建。
在构建 MediaPlayerWizard.cpp 时
在项目构建之前,您是否尝试过手动运行qmake
?
@GenericMadman 清理你的构建目录。您特别需要在再次构建之前删除文件 mediaplayerwizard_h.h。
【参考方案1】:
您需要将成员函数标记为槽才能将其用作槽。 所以,尝试更改声明
void btnActivateClicked();
与
private slots:
void btnActivateClicked();
或
Q_SLOT void btnActivateClicked();
【讨论】:
【参考方案2】:您需要删除构建目录并重新构建解决方案。重建无法工作,因此请删除构建目录。这是an old Qt issue。
【讨论】:
@GenericMadman 你能剪切确切的错误信息并粘贴到这里吗?你确定上面显示的代码是你正在编译的吗? 我已将其添加到主帖底部。 @GenericMadman 正如@Andrey 所指出的btnActivateClicked
是Q_SLOT
。您是否尝试过按照他的建议进行操作并在此之后删除构建目录?
@JacobKrieg 是的,我尝试了这两种方法,但没有这样的运气。
所以我拿了你的代码并做了一个测试应用程序,对我来说它工作正常。我上传了我的项目,以便您进行比较...fileshare.ro/e30893428。您能否告诉我们您的项目是否使用shadow build
?如果您没有使用shadow build
,那么文件将生成在与源相同的文件夹中,并且您可能没有删除所有生成的文件。我真的建议在您的项目中使用shadow build
。【参考方案3】:
您需要在 mediaplayerwizard.h 中取消注释 //Q_OBJECT
,该行应仅包含 Q_OBJECT
并将 void btnActivateClicked();
定义为插槽。
【讨论】:
我认为您需要再次阅读该问题。然后再一次。 他发布的代码包含注释掉的这一行,他得到了应该添加 Q_OBJECT 宏的错误。实际上,信号和槽的使用无论如何都需要定义Q_OBJECT。 他的问题是,当他添加Q_OBJECT宏时出现错误。以上是关于Q_OBJECT 导致“未定义的 v_table 引用”问题的主要内容,如果未能解决你的问题,请参考以下文章