Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Qt:缺少vtable通常意味着第一个非内联虚拟成员函数没有定义_Qt_Clang - Fatal编程技术网

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_对象
    做两件事:

  • 它告诉builsystems添加对
    moc
    的调用,moc的任务是为类生成一些额外的代码。本规范将提供上述所有设施
  • 因为它是一个普通的C++宏,编译时<>强> <强>,包括几个虚拟:<代码> QTyMeta()/<代码>和<代码>元对象()/<代码>。code>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"