QT Creator链接器错误:未找到Link2019文件

时间:2016-04-27 05:39:15

标签: c++ qt linker qt-creator header-files

我不太确定我的问题在哪里。

我正在使用Qt Creator进行OpenGL项目,并且我第一次尝试在我的项目中添加另外几个类。我已经添加了header和implementation文件: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的交互方式。

当我删除所有对terrain的引用时,构建工作正常。

但是当我在initializeGL()方法中将以下行添加到glwidget.cpp时,会出现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时,或删除build文件夹中的.obj文件时,没有任何更改。我注意到重建项目时会出现glwidget.obj以及terrain.obj。

感谢任何帮助。如果您想查看我的任何文件,请告诉我。

编辑:即使将loadTerrain()方法设为非静态问题,问题仍然存在。

编辑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);

以及更改对方法的后续调用。

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

通过创建函数static,您可以使用内部链接。这意味着您的函数定义只能在定义它的翻译单元中找到(即terrain.cpp)而不是main.cpp。删除static关键字。

使用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

它出现两次!这就是为什么你不要在头文件中使函数静态,以便在多个翻译单元之间共享。

答案 1 :(得分:0)

似乎你在glwidget.cpp中缺少函数loadTerrain()的实现:

Terrain* loadTerrain(const char* fileName, float height)
{
   // your implementation here
}

您可以查看here样本。