带有虚函数的未解析外部符号

Unresolved External Symbol with virtual functions

本文关键字:外部 符号 函数      更新时间:2023-10-16

我试图通过使用qt设计模式的例子来了解虚拟函数的行为

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

#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;
}

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

主要。obj:-1:错误:LNK2001:未解析的外部符号"public "虚拟void __cdecl A::foo(类QTextStream &)"(? foo@A@@UEAAXAEAVQTextStream@@@Z)

主要。obj:-1:错误:LNK2001:未解析的外部符号"public "虚拟void __cdecl A::bar(类QTextStream &)"(? bar@A@@UEAAXAEAVQTextStream@@@Z)

,因为我对虚函数知之甚少。我想它可能需要在B类中重新声明函数,但这也没有帮助,并在我的日志中添加了2个错误。

主要。obj:-1:错误:LNK2001:未解析的外部符号"public "虚拟void __cdecl B::foo(类QTextStream &)"(? foo@B@@UEAAXAEAVQTextStream@@@Z)

主要。obj:-1:错误:LNK2001:未解析的外部符号"public "虚拟void __cdecl B::bar(类QTextStream &)"(? bar@B@@UEAAXAEAVQTextStream@@@Z)

book示例只是在声明函数后(在同一个文件中)实现函数,这似乎行得通。我想知道为什么我的不工作,如果有一个解决方案

编辑:

项目文件使用以下设置:

#-------------------------------------------------
#
# 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

我不得不说,我没有太多的想法,当它涉及到建设,链接的东西,但我不应该需要关注他们现在为一个小项目。由于abclasses .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);
}

EDIT 2:更新了过时的错误信息,更新了abclasses.h

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

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

但是Qt Creator直接调用Makefile.releaseMakefile.debug作为需要分别发布/调试构建。这将绕过仅存在于基本Makefile中的makefile再生规则。正是这种交互是bug/错误行为的来源,(不幸的是)影响到Windows上Qt Creator的每个用户。

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

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

你能更新一下这个问题吗?你说你在B类做了修改,请更新即使是新遇到的错误。

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

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

好的,这是在互联网上挖掘类似问题后的结果。qt创建者有时不能真正告诉它是否应该更新"make"文件,我多少意识到这一点,因此在一些大的改变后使用"clean"。但问题是,清理或重建并不能像我希望的那样完全工作。所以在一些建议之后,我手动删除了构建文件夹,现在它编译并正常运行。