Qt:缺少vtable通常意味着第一个非内联虚拟成员函数没有定义
这上面有很多。似乎没有一个符合我的要求。我的代码中出现以下链接器错误:Qt:缺少vtable通常意味着第一个非内联虚拟成员函数没有定义,qt,clang,Qt,Clang,这上面有很多。似乎没有一个符合我的要求。我的代码中出现以下链接器错误: Undefined symbols for architecture x86_64: "vtable for MSFSPlugin::MSFSPluginImpl", referenced from: MSFSPlugin::MSFSPluginImpl::MSFSPluginImpl(QObject*) in MSFSPlugin.o MSFSPlugin::MSFSPluginImpl::~M
Undefined symbols for architecture x86_64:
"vtable for MSFSPlugin::MSFSPluginImpl", referenced from:
MSFSPlugin::MSFSPluginImpl::MSFSPluginImpl(QObject*) in MSFSPlugin.o
MSFSPlugin::MSFSPluginImpl::~MSFSPluginImpl() in MSFSPlugin.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
这应该是显而易见的——缺少vtable通常意味着第一个非内联虚拟成员函数没有定义。但是,我看不出我遗漏了什么:
我在MSFSPlugin.h
中定义了这个类:
class MSFSPlugin
:
public QObject,
public IMediaSource
{
Q_OBJECT
Q_INTERFACES(IMediaSource)
...
protected:
class MSFSPluginImpl;
MSFSPluginImpl* mImpl;
}
然后在MSFSPlugin.cpp
中,我有以下内容:
class MSFSPlugin::MSFSPluginImpl : public QThread
{
Q_OBJECT
public:
MSFSPluginImpl(QObject *parent = 0);
virtual ~MSFSPluginImpl();
QString getSourceDirectory() const;
void setSourceDirectory(QString sourceDirectory);
signals:
void loadDirectoryFinished(bool success);
protected:
QString mSourceDirectory;
};
其次是定义:
MSFSPlugin::MSFSPluginImpl::MSFSPluginImpl(QObject *parent) : QThread(parent)
{
}
MSFSPlugin::MSFSPluginImpl::~MSFSPluginImpl()
{
}
QString MSFSPlugin::MSFSPluginImpl::getSourceDirectory() const
{
return mSourceDirectory;
}
void MSFSPlugin::MSFSPluginImpl::setSourceDirectory(QString sourceDirectory)
{
mSourceDirectory = sourceDirectory;
}
...
简而言之,我不认为我缺少任何非内联虚拟成员函数定义。我正在使用:
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix
其他信息:
在我的moc_MSFSPlugin.cpp
中,我没有看到类MSFSPlugin::MSFSPluginImpl
的自动生成的Q_对象
相关代码,该类间接(通过QThread)派生自QObject
。具体来说,我没有看到为该类中声明的信号生成的代码(loadDirectoryFinished
)。这可能是问题所在吗
编辑1:
如果我从MSFSPlugin::MSFSPluginImpl
的定义中注释掉Q_OBJECT
,错误就会消失,但随后我就失去了信号功能
编辑2:
我看到moc只在头文件上运行。这是否与我的QObject派生类在.cpp文件中声明和定义有关
编辑1:如果我从MSFSPlugin::MSFSPluginImpl的degration中注释掉Q_对象,错误就会消失,但随后我就失去了信号功能
是的,Q_对象宏对于信号、插槽、属性等是必需的
编辑2:我看到moc仅对头文件进行操作。这是否与我的QObject派生类在.cpp文件中声明和定义有关
是和否。我会解释的
通常,在编写时可以通过分离来解决这个问题,但也可以在类定义之后包含moc文件,以使其正常工作,但您需要记住不要在其中放置多个文件,以避免奇怪的后果
因此,在您的例子中,您可以为实现头建立一个MSFSPlugin\u p.h
或MSFSPluginImpl.h
文件
顺便说一句,保护pimpl是个坏主意。pimpl习惯用法表示私有实现,不受保护。假设我们处理的是qmake
黄金法则是:
QObject
派生类的定义中都存在Q_对象
宏李>
QObject
派生类李>
HEADERS=
列表的.pro文件中李>
Q\u对象
添加到某个类或修改.pro
文件时,请运行qmake
解释 编辑1:如果我从MSFSPlugin::MSFSPluginImpl的degration中注释掉Q_对象,错误就会消失,但随后我就失去了信号功能 是的
Q_对象
用于声明信号、插槽、可调用项、qobject_cast
、翻译、属性、枚举和方法内省等
#1黄金法则来自这样一个事实:没有Q_OBJECT
你就不能在你的课堂上使用qobject\u cast
;如果使用(甚至间接地)内省功能,例如to或to,那么类的对象将显示真实的类名(而不是超类的名称);等等
Q_对象
做两件事:
moc
的调用,moc的任务是为类生成一些额外的代码。本规范将提供上述所有设施李>
moc
未运行,您有一些未实现的虚拟现实,这将导致链接失败
使用gcc和gnuld,您会得到一个更为隐晦的错误,关于类名对vtable的未定义引用。当然,谷歌搜索这些错误会立即告诉你如何解决这个问题
编辑2:我看到moc仅对头文件进行操作。这是否与我的QObject派生类在.cpp文件中声明和定义有关
所以,问题是:moc
为什么不在一个包含类定义的文件上运行,该类定义包含Q_对象
宏
当我们使用qmake
生成makefile时,qmake将扫描HEADERS
变量中列出的所有头文件。当它发现一个头包含一个带有Q_OBJECT
宏的类定义时,它还将发出指令(在Makefile中)在该头上运行moc
,编译moc
的输出并将结果对象链接到最终目标中
我们这里有规则#2、#3、#4
#2告诉我们将Q_对象
类放在标题中;这是因为HEADERS
列出了头,而不是源
#3告诉我们确实要将所有标题放入headers
列表中。这显然是因为如果包含Q_对象的头不在该列表中,那么qmake
将找不到它并发出规则。(虽然对于不包含QObject子类的头不是严格必需的,但最好将每个头都放在其中,以便不忘记任何头。)
#4告诉我们每次添加Q_对象
或修改.pro
#include "foobar.moc"