Qt creator:c ++:对Class :: Function的未定义引用

时间:2013-06-04 12:20:10

标签: c++ qt unit-testing qt-creator include-path

我在Qt创建者中创建了两个c ++项目。第一个是Application project,另一个是unit-test project。这两个项目分开,工作正常。然而,当把两者连接在一起时,我面临一个小问题。

我在#INCLUDEPATH applicationProjectPath的{​​{1}}中加入.pro file。然后来自unit-test project的{​​{1}}中的应用项目的#include myClass。然后,从main.cpp创建unit-test project并调用该对象中的函数。

编译时,会出现此错误:

myObject

然而,当将myClass添加到单元测试项目的.pro文件中时(同时保留undefined reference to `myObject::function' ),一切正常(即:执行测试单元)

从.pro中删除#SOURCES applicationProjectPath/myClass.cpp时再次崩溃。

我想如果我包含#INCLUDEPATH applicationProjectPath,那么我就不需要包含#INCLUDEPATH。如果我包含#SOURCES,我不应该包含#INCLUDEPATH(至少不包括完整路径,只包括.cpp文件,然后编译器应查找两个目录,默认目录和添加的目录一)。

所以,我的问题是:为什么会发生这种情况

2 个答案:

答案 0 :(得分:4)

您的单元测试需要编译项目中要进行单元测试的类。因此,您需要在两个项目中添加include(否则测试项目将不知道您要测试的类)。并且链接器也需要链接到项目的代码,因为您的测试将使用类。

一种方法是在测试项目中添加要测试的类,并在编译单元测试项目时再次编译它们,但这很乏味,而且每次想要添加类时都不太方便,需要将它添加到两个.pro文件中(提示,您可以在.pro文件中使用通配符,如* .cpp将文件夹中的所有源文件添加到项目中)。

在我看来,更好的方法是将要测试的项目设置为静态库,将其与应用程序分开:您有另一个项目是应用程序,只包含链接到该静态的main.cpp库。

以下是包含项目的文件夹的表示形式:

Project.pro #subdir project
UIProject/ #static lib
    UIProject.pro
    #all your classes here
MainProject/ #application
    MainProject.pro
    main.cpp
UITestProject/ #unit tests of UIProject (linking to it)
    UITestProject.pro
    #all your UI test classes here

Project.pro:

TEMPLATE = subdirs
SUBDIRS += UIProject
SUBDIRS += MainProject
SUBDIRS += UITestProject

UIProject.pro:

# project type
TEMPLATE = lib

# library type
CONFIG += staticlib

HEADERS += *.h
SOURCES += *.cpp

MainProject.pro:

#[...]
TEMPLATE = app
SOURCES += main.cpp
INCLUDEPATH += ../UIProject/
DEPENDPATH += $${INCLUDEPATH} # force rebuild if the headers change

# link against UILib
_UI_LIB = ../UIProject/
CONFIG(debug, debug|release) {
    win32: _UI_LIB = $$join(_UI_LIB,,,debug/UIProject.lib)
} else {
    win32: _UI_LIB = $$join(_UI_LIB,,,release/UIProject.lib)
}
LIBS += $${_UI_LIB}
PRE_TARGETDEPS += $${_UI_LIB}

UITestProject.pro:

#[...]
TEMPLATE = app
HEADERS += *.h
SOURCES += *.cpp

INCLUDEPATH += ../UIProject/
DEPENDPATH += $${INCLUDEPATH} # force rebuild if the headers change

# link against UILib
_UI_LIB = ../UIProject/
CONFIG(debug, debug|release) {
    win32: _UI_LIB = $$join(_UI_LIB,,,debug/UIProject.lib)
} else {
    win32: _UI_LIB = $$join(_UI_LIB,,,release/UIProject.lib)
}
LIBS += $${_UI_LIB}
PRE_TARGETDEPS += $${_UI_LIB}

你必须编辑它以匹配你的项目,但主要的事情在这里。它应该像我从我的一个项目中复制它一样,只要我没有添加任何错误。

答案 1 :(得分:2)

您应该将cpp文件包含到项目中,以告知构建系统(qmake)编译给定文件。

  

当您将myClass.cpp添加到测试项目时,它会被编译,否则就会被编译。

因此,当您不将cpp文件添加到项目中时,您将收到 linker 错误。

包含只是单独处理

当您向INCLUDEPATH添加新路径时,编译器会将该传递添加到标题搜索列表

  

当您将applicationProjectPath添加到包含路径时,编译器将在那里搜索标头。重要的是,允许编译器找到myClass.h

如果您不添加标题搜索列表的路径,编译器将无法编译您的main.cpp,并且您将收到编译错误。

但是,您可以在测试项目的主要部分中指定myClass.h的(相对)路径:

#include "../applicationProjectPath/myClass.h"

总结

您需要将源文件添加到测试项目将标题路径添加到测试项目的包含搜索列表。

进一步阅读

What is an undefined reference/unresolved external symbol error and how do I fix it?