具有虚函数的未解析外部符号
Unresolved External Symbol with virtual functions
我试图通过使用 qt 设计模式中的示例来了解虚函数的行为方式
这里我有一个头文件,其中定义了 2 个 classes:
#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
这是 classes
的源文件
#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;
}
问题是我无法根据这些定义创建或使用任何 classes。我得到的错误是
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)
因为我对虚函数了解不多。我认为可能需要重新声明 class 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
你能更新问题吗?正如您所说,您在 class B 中进行了修改,请更新它。即使是新遇到的错误。
private: virtual void __cdecl B::bar(class QTextStream &)" (?
从这个错误来看,class B 中的 bar 函数似乎是私有的。
好的,这是在互联网上搜索类似问题后的结果。
qt creator 有时不能真正判断它是否应该更新 "make" 文件,我有点意识到这一点,因此在一些大的变化之后使用 "clean"。
但问题是干净的或重建没有像我希望的那样完全工作。所以在一些建议之后,我手动删除了构建文件夹,现在它可以正常编译和运行了。
abclassess.cpp
文件未编译,因为 makefile 与 .pro
文件相比已过时。在Qt Creator中右击最顶层的项目节点,select Run qmake
。然后重新构建项目。
不幸的是,Qt Creator 和 qmake 之间的不良交互表现在 Windows。在该平台上,qmake 生成三个 makefile:Makefile
、Makefile.release
和 Makefile.debug
。不幸的是,只有顶级 makefile 在 .pro
文件和 makefile 之间具有适当的依赖性:每当项目文件更改时,make 调用 qmake 将自动重新生成 makefile。通常这不会成为问题,因为当您手动构建时,您会调用顶部的 nmake/jom Makefile
.
但 Qt Creator 会根据 release/debug 构建的需要分别直接调用 Makefile.release
或 Makefile.debug
。这会绕过仅存在于基础 Makefile
中的 makefile 重新生成规则。正是这种交互是 bug/misbehavior 的来源,(不幸的是)目前影响 Windows 上的每个 Qt Creator 用户。
因此,您必须在每次更改项目文件后调用 qmake - 例如,每次添加或修改源文件时。
有一个简单的解决方法 - 添加一个调用基础 Makefile
的构建步骤到项目配置的构建中。
我试图通过使用 qt 设计模式中的示例来了解虚函数的行为方式
这里我有一个头文件,其中定义了 2 个 classes:
#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
这是 classes
的源文件#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;
}
问题是我无法根据这些定义创建或使用任何 classes。我得到的错误是
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)
因为我对虚函数了解不多。我认为可能需要重新声明 class 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
你能更新问题吗?正如您所说,您在 class B 中进行了修改,请更新它。即使是新遇到的错误。
private: virtual void __cdecl B::bar(class QTextStream &)" (?
从这个错误来看,class B 中的 bar 函数似乎是私有的。
好的,这是在互联网上搜索类似问题后的结果。 qt creator 有时不能真正判断它是否应该更新 "make" 文件,我有点意识到这一点,因此在一些大的变化之后使用 "clean"。 但问题是干净的或重建没有像我希望的那样完全工作。所以在一些建议之后,我手动删除了构建文件夹,现在它可以正常编译和运行了。
abclassess.cpp
文件未编译,因为 makefile 与 .pro
文件相比已过时。在Qt Creator中右击最顶层的项目节点,select Run qmake
。然后重新构建项目。
不幸的是,Qt Creator 和 qmake 之间的不良交互表现在 Windows。在该平台上,qmake 生成三个 makefile:Makefile
、Makefile.release
和 Makefile.debug
。不幸的是,只有顶级 makefile 在 .pro
文件和 makefile 之间具有适当的依赖性:每当项目文件更改时,make 调用 qmake 将自动重新生成 makefile。通常这不会成为问题,因为当您手动构建时,您会调用顶部的 nmake/jom Makefile
.
但 Qt Creator 会根据 release/debug 构建的需要分别直接调用 Makefile.release
或 Makefile.debug
。这会绕过仅存在于基础 Makefile
中的 makefile 重新生成规则。正是这种交互是 bug/misbehavior 的来源,(不幸的是)目前影响 Windows 上的每个 Qt Creator 用户。
因此,您必须在每次更改项目文件后调用 qmake - 例如,每次添加或修改源文件时。
有一个简单的解决方法 - 添加一个调用基础 Makefile
的构建步骤到项目配置的构建中。