【问题标题】:Unresolved External Symbol with virtual functions具有虚函数的未解析外部符号
【发布时间】:2015-11-17 01:00:19
【问题描述】:

我正在尝试通过使用带有 qt 的设计模式中的示例来了解虚拟函数的行为

这里我有一个头文件,其中定义了 2 个类:

#ifndef ABCLASSES_H
#define ABCLASSES_H
#include <QTextStream>

class A
{
public:
    virtual ~A()
    {

    }
    virtual void foo(QTextStream& out);
    virtual void bar(QTextStream& out);
};

class B: public A
{
public:
    void foo(QTextStream& out);
    void bar(QTextStream& out);
};

#endif // ABCLASSES_H

这是这些类的源文件

#include "abclasses.h"

void A::foo(QTextStream& out)
{
    out << "A's foo" << endl;
    bar(out);
}

void A::bar(QTextStream& out)
{
    out << "A's bar" << endl;
}

void B::foo(QTextStream& out)
{
    out << "B's foo" << endl;
    A::bar(out);
}

void B::bar(QTextStream& out)
{
    out << "B's bar" << endl;
}

问题是我无法从这些定义中创建或使用任何类。我得到的错误是

main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual void __cdecl A::foo(class QTextStream &)" (?foo@A@@UEAAXAEAVQTextStream@@@Z)

main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual void __cdecl A::bar(class QTextStream &)" (?bar@A@@UEAAXAEAVQTextStream@@@Z)

因为我对虚函数了解不多。我认为可能需要重新声明 B 类中的函数,但这也无济于事,并在我的日志中增加了 2 个错误。

main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual void __cdecl B::foo(class QTextStream &)" (?foo@B@@UEAAXAEAVQTextStream@@@Z)

main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual void __cdecl B::bar(class QTextStream &)" (?bar@B@@UEAAXAEAVQTextStream@@@Z)

本书示例只是在声明函数后(在同一个文件中)实现了函数,这似乎可行。我想知道为什么我的不起作用以及是否有解决方法

编辑: 项目文件使用以下设置:

#-------------------------------------------------
#
# Project created by QtCreator 2015-08-23T11:53:16
#
#-------------------------------------------------

QT       += core

QT       -= gui

TARGET = untitled1
CONFIG   += console
CONFIG   -= app_bundle

TEMPLATE = app


SOURCES += main.cpp \
    student.cpp \
    abclasses.cpp

HEADERS += \
    student.h \
    abclasses.h

我不得不说,在构建、链接东西方面我没有太多想法,但我现在不应该将它们集中在一个小项目上。由于 abclases.cpp 在来源中,我认为它用于构建过程。

student.h 和 .cpp 与我在同一个项目中的另一个试用有关。它们现在没有被积极使用,下面是 main.cpp

#include <QCoreApplication>
#include <QTextStream>
//#include "student.h"
#include "abclasses.h"

//void finish(Student& student)
//{
//    QTextStream cout(stdout);
//    cout << "The following " << student.getClassName()
//         << "has applied for graduation" << endl
//         << student.toString() << endl;
//}

int main() {
    QTextStream cout(stdout);
    B bobj;
//    A *aptr = &bobj;
//    aptr->foo(cout);
//    cout << "-------------" << endl;
//    A aobj = *aptr;
//    aobj.foo(cout);
//    cout << "-------------" << endl;
//    aobj = bobj;
//    aobj.foo(cout);
//    cout << "-------------"<< endl;
//    bobj.foo(cout);
}

编辑 2:更新过时的错误消息,更新 abclasses.h

【问题讨论】:

  • 必须B类中声明被覆盖的函数。
  • 至于您的问题,您实际上是在构建 包含函数定义的源文件吗?我怀疑你也打算在Bpublic 中创建这些功能。
  • 我尝试在“public:”下的 B 类中声明它们,但正如我所说,它只是向我介绍了另外 2 个错误。由于我无法真正有效地使用此编辑器,因此我正在更新有关“构建”部分的问题。
  • 听起来 abclasses.cpp 没有被编译和/或链接。你能发布'make'的输出吗?
  • 尽管我在 qt 中重建项目之前反复使用 clean,但它给出了相同的错误。但是在手动删除项目文件夹后,错误就消失了。感谢您为我指明正确的方向。 现在我要搜索关于 qt clean 方法的错误报告。

标签: c++ qt external virtual symbols


【解决方案1】:

abclassess.cpp 文件未编译,因为与.pro 文件相比,makefile 已过期。右键单击 Qt Creator 中最顶部的项目节点,然后选择 Run qmake。然后重新构建项目。

不幸的是,这是在 Windows 上表现出来的 Qt Creator 和 qmake 之间的不良交互。在该平台上,qmake 生成三个 makefile:MakefileMakefile.releaseMakefile.debug。不幸的是,只有顶级makefile 在.pro 文件和makefile 之间具有适当的依赖关系:每当项目文件更改时,makefile 将通过调用qmake 自动重新生成。通常这不会有问题,因为当您手动构建时,您会在顶部调用 nmake/jom Makefile

但 Qt Creator 会根据需要分别直接调用 Makefile.releaseMakefile.debug 以进行发布/调试构建。这绕过了仅存在于基础 Makefile 中的 makefile 重新生成规则。正是这种交互是目前(不幸地)影响 Windows 上 Qt Creator 的每个用户的错误/不当行为的根源。

因此,您必须在每次更改项目文件后调用 qmake - 例如,每次添加或修改源文件时。

有一个简单的解决方法 - 将调用基础 Makefile 的构建步骤添加到项目配置的构建中。

【讨论】:

    【解决方案2】:

    你能更新问题吗?正如您所说,您在 B 类中进行了修改,请更新。甚至是新遇到的错误。

    private: virtual void __cdecl B::bar(class QTextStream &)" (?
    

    从这个错误来看,B 类中的 bar 函数似乎是私有的。

    【讨论】:

      【解决方案3】:

      好的,这是在互联网上挖掘类似问题后的结果。 qt 创建者有时无法真正判断它是否应该更新“make”文件,我有点意识到这一点,因此在进行了一些重大更改后使用了“clean”。 但问题是干净或重建并没有像我希望的那样完全工作。所以经过一些建议,我手动删除了构建文件夹,现在它可以正常编译和运行了。

      【讨论】:

      • 这实际上不是 Qt Creator 的工作——除了在项目的第一次构建中调用 qmake 之外,Qt Creator 不负责更新任何内容。 makefile 本身应该依赖于项目文件,以便 make 可以自己调用 qmake 来重新生成 makefile。不幸的是,Creator 调用 makefile 的方式暴露了 Creator 与 qmake 的不良交互。
      • 感谢您的回答,但我不明白一件事:为什么 qt 不需要更新 q​​make?如果他们的依赖关系没有正确链接,那么他们应该在每次更改时重建它
      • 最终,这是一个错误 - 我不知道这是一个 qmake 错误还是一个 Qt Creator 错误,因为孤立地两者都做正确的事情,这是他们的交互错误。某个地方的某个人需要修复它。即使它被修复,Qt Creator 也不会直接重新创建任何东西。制作工具会。但是现在 make 工具(不是qmake,不是 Qt 中的任何东西)并没有这样做,因为没有人愿意告诉它......所以,把它当作一个错误的地方,用一个微不足道的解决方法。一旦你配置你的项目来解决它,你就不会再有这个问题了。
      猜你喜欢
      • 2012-05-22
      • 2014-04-20
      • 2013-11-03
      • 2013-03-04
      • 1970-01-01
      • 2013-02-22
      • 1970-01-01
      • 2014-06-13
      相关资源
      最近更新 更多