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

时间:2015-08-23 15:10:04

标签: c++ qt external virtual symbols

我试图通过使用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;
}

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

  

main.obj:-1:错误:LNK2001:未解析的外部符号“public:   virtual void __cdecl A :: foo(class QTextStream&amp;)“   (?FOO @ @@甲@@@ UEAAXAEAVQTextStream Z)

     

main.obj:-1:错误:LNK2001:未解析的外部符号“public:   virtual void __cdecl A :: bar(类QTextStream&amp;)“   (?条@ @@甲@@@ UEAAXAEAVQTextStream Z)

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

  

main.obj:-1:错误:LNK2001:未解析的外部符号“public:   virtual void __cdecl B :: foo(class QTextStream&amp;)“   (?FOO @ @@乙@@@ UEAAXAEAVQTextStream Z)

     

main.obj:-1:错误:LNK2001:未解析的外部符号“public:   virtual void __cdecl B :: bar(类QTextStream&amp;)“   (?条@ @@乙@@@ 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

3 个答案:

答案 0 :(得分:0)

你能否请更新问题?正如您所说,您已在B级进行了修改,请更新。即使是新面临的错误。

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

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

答案 1 :(得分:0)

好的,这是在挖掘互联网以解决类似问题后的结果。 qt创建者有时无法确定它是否应该更新“make”文件,我有点意识到这一点,因此在经过一些重大改变后使用“干净”。 但问题是干净或重建并不是我想要的全部工作。所以经过一些建议,我手动删除了构建文件夹,现在它编译并正常运行。

答案 2 :(得分:0)

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

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

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

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

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