我不太确定我的问题出在哪里。
我正在为一个 OpenGL 项目使用 Qt Creator,这是我第一次尝试向我的项目添加另外几个类。我添加了头文件和实现文件:terrain.h、terrain.cpp、imageloader.h 和 imageloader.cpp。
我认为我的问题在于我的 .pro 文件:
HEADERS += glwidget.h \
imageloader.h \
terrain.h
SOURCES += glwidget.cpp main.cpp \
imageloader.cpp \
terrain.cpp
QT += opengl
CONFIG -= app_bundle
CONFIG += console c++11
INCLUDEPATH += "../include"
INCLUDEPATH += $$PWD
RESOURCES += shaders.qrc
当我运行 qmake 时,没有错误。
然后,当我构建项目时(清理后,运行 qmake),出现以下错误:
glwidget.obj:-1: error: LNK2019: unresolved external symbol "private: static class Terrain * __cdecl GLWidget::loadTerrain(char const *,float)" (?loadTerrain@GLWidget@@CAPEAVTerrain@@PEBDM@Z) referenced in function "protected: virtual void __cdecl GLWidget::initializeGL(void)" (?initializeGL@GLWidget@@MEAAXXZ)
Qt Creator 还说:找不到文件 glwidget.obj
然而,问题似乎真的出在地形类上,或者它如何与 glwidget 交互。
当我删除所有对地形的引用时,构建工作正常。
但是,当我在 glwidget.cpp 的 initializeGL() 方法中添加以下行时,出现 LINK2019 错误:
terrain = loadTerrain("test.bmp", 20);
terrain 在 glwidget.h 中定义为 terrain.cpp 中的 Terrain 类的实例:
Terrain* terrain;
并且 loadTerrain 在 glwidget.h 中定义为:
static Terrain* loadTerrain(const char* filename, float height);
有趣的是,即使注释掉了 loadTeerain 的实现,也会出现此错误。
以下是我尝试过的其他一些方法:
当我在 qmake 之前或之后运行 clean,或者删除构建文件夹中的 .obj 文件时,没有任何变化。我注意到重建项目时确实出现了 glwidget.obj 和 terrain.obj。
感谢任何帮助。如果您想查看我的任何文件,请告诉我。
编辑:即使在使 loadTerrain() 方法成为非静态方法后问题仍然存在。
EDIT 2 我似乎也忘记了它抛出的第二个错误,尽管我不确定这是否会有更多帮助:
debug\program2.exe:-1: error: LNK1120: 1 unresolved externals
debug 是 .obj 出现的文件夹,program2 是项目的名称。
已修复!事实证明,将方法设为静态是问题所在。你不能在头文件中声明一个静态方法,而这些方法将以我正在做的方式被多个源使用。我替换了:
static Terrain* loadTerrain(const char* filename, float height);
与
Terrain* GLWidget::loadTerrain(const char* filename, float height);
以及更改对该方法的后续调用。
感谢您的帮助!
最佳答案
通过使函数static
,你给了它内部链接。这意味着您的函数的定义只能在定义它的翻译单元中找到(即 terrain.cpp
),而不是 main.cpp
。删除静态关键字。
这很容易用 objdump
确认。假设你有 test.h
:
#ifndef _TEST_H
#define _TEST_H
static void a_func();
#endif
test.cpp
:
#include "test.h"
void a_func()
{
}
main.cpp
:
#include "test.h"
void a_func()
{
}
int main()
{
}
您会注意到您不会收到函数重定义错误。我们可以分别编译每个文件来检查对象:
g++ -c test.cpp -o test.o
g++ -c main.cpp -o main.o
两者都会显示a_func
:
Disassembly of section .text:
0000000000000000 <_ZL6a_funcv>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 90 nop
5: 5d pop %rbp
6: c3 retq
那么最终的二进制文件呢?
g++ main.o test.o
objdump -d ./a.out
00000000004005b6 <_ZL6a_funcv>:
4005b6: 55 push %rbp
4005b7: 48 89 e5 mov %rsp,%rbp
4005ba: 90 nop
4005bb: 5d pop %rbp
4005bc: c3 retq
00000000004005bd <main>:
4005bd: 55 push %rbp
4005be: 48 89 e5 mov %rsp,%rbp
4005c1: b8 00 00 00 00 mov $0x0,%eax
4005c6: 5d pop %rbp
4005c7: c3 retq
00000000004005c8 <_ZL6a_funcv>:
4005c8: 55 push %rbp
4005c9: 48 89 e5 mov %rsp,%rbp
4005cc: 90 nop
4005cd: 5d pop %rbp
4005ce: c3 retq
4005cf: 90 nop
它出现了两次!这就是为什么您不在要在多个翻译单元之间共享的头文件中将函数设为静态。
关于c++ - QT Creator 链接器错误 : Link2019 File Not Found,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36881168/