如何解决错误LNK2019:无法解析的外部符号-功能?


99

我收到此错误,但是我不知道如何解决。

我使用的是Visual Studio2013。我将解决方案的名称命名为MyProjectTest, 这是我的测试解决方案的结构:

结构

- function.h

#ifndef MY_FUNCTION_H
#define MY_FUNCTION_H

int multiple(int x, int y);
#endif

-function.cpp

#include "function.h"

int multiple(int x, int y){
    return x*y;
}

- main.cpp中

#include <iostream>
#include <cstdlib>
#include "function.h"
using namespace std;

int main(){
    int a, b;
    cin >> a >> b;
    cout << multiple(a, b) << endl;

    system("pause");
    return 0;
}

我是初学者;这是一个简单的程序,它运行没有错误。我在互联网上阅读并对单元测试感兴趣,因此创建了一个测试项目:

文件>新建>项目...>已安装>模板> Visual C ++>测试>本机单元测试项目>

名称:UnitTest1 解决方案:添加到解决方案 然后位置自动切换到当前打开的解决方案的路径这是解决方案的文件夹结构:

资料夹结构

我只编辑了unittest1.cpp文件:

#include "stdafx.h"
#include "CppUnitTest.h"
#include "../MyProjectTest/function.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace UnitTest1
{       
    TEST_CLASS(UnitTest1)
    {
    public:

        TEST_METHOD(TestEqual)
        {

            Assert::AreEqual(multiple(2, 3), 6);
            // TODO: Your test code here
        }

    };
}

但是我收到错误LNK2019:无法解析的外部符号。我知道缺少函数multi的实现。我试图删除function.cpp文件,并用定义替换了声明,然后它开始运行。但是不建议将声明和定义都写在同一个文件中。如果不这样做,如何解决此错误?是否应该#include "../MyProjectTest/function.cpp"在unittest.cpp文件中替换为? (我不太会英语。谢谢)



6
注意Windows环境中,静态库具有.LIB文件扩展名。使事情复杂化的是...动态链接库(即*.DLL)可以具有一个随附的导入库,该导入库也具有.LIB文件扩展名。此导入库列出了所提供的所有商品*.DLL。有关更多信息,请阅读:链接程序入门指南
Pressacco

4
他为什么要小心?
元帅工艺

Answers:


80

一种选择是将其包含function.cpp在您的UnitTest1项目中,但这可能不是最理想的解决方案结构。对您的问题的简短回答是,在构建UnitTest1项目时,编译器和链接器不知道function.cpp存在,也没有包含定义的链接multiple。解决此问题的一种方法是利用链接库。

由于您的单元测试在另一个项目中,所以我假设您的意图是使该项目成为独立的单元测试程序。使用位于另一个项目中的要测试的功能,可以将该项目构建为动态或静态链接的库。静态库在构建时链接到其他程序,并且具有扩展名.lib,而动态库在运行时链接到,并且具有扩展名.dll。对于我的答案,我更喜欢静态库。

您可以通过在项目属性中进行更改将第一个程序转换为静态库。在“常规”选项卡下应该有一个选项,其中将项目设置为构建为可执行文件(.exe)。您可以将其更改为.lib。该.lib文件将与建立在同一位置.exe

在您的UnitTest1项目中,可以转到其属性,然后在“其他库目录”类别的“链接器”选项卡下,添加MyProjectTest构建路径。然后,对于“链接程序-输入”选项卡下的“其他依赖关系”,添加静态库的名称(最有可能是)MyProjectTest.lib

那应该可以使您的项目得以构建。请注意,这样做MyProjectTest将不会成为独立的可执行程序,除非您根据需要更改其构建属性,这将不理想。


在“链接器->输入选项卡”中,我必须为静态库添加前缀“(OutDir)”,即“ $(OutDir)MyProjectTest.lib”,尽管“ MyProject”和“ MyTestProject”的位置都位于同一根文件夹中。
Pabitra Dash

13
因此,每次要运行单元测试时,都应将测试对象项目转换为静态库,并且在每次实际要运行程序的地方,都将其转换回可执行文件,这是一个解决方案?
A. Smoliak

1
如果MyProjectTest是dll,我们可以测试它吗?我们只是添加导入库,还是必须添加obj文件?
aviit,

“您可以通过在项目属性中对其进行更改来将第一个程序转换为静态库。“常规”选项卡下应该有一个选项,其中该项目设置为构建为可执行文件(.exe)。您可以将其更改为.lib .lib文件将与.exe放置在相同的位置。其余的已经由VS处理。
Ekrem Solmaz


17

因为我希望我的项目编译为独立的EXE,所以我将UnitTest项目链接到从function.cpp生成的function.obj文件,它可以工作。右键单击“ UnitTest1”项目>配置属性>链接器>输入>其他依赖关系>添加“ .. \ MyProjectTest \ Debug \ function.obj”


1
MyProjectTest是dll的情况如何?你可以设置吗?
aviit

如果我们有很多obj文件。我们可以添加诸如* .obj这样的东西吗?您的解决方案与我合作,但我不想手动添加每个新的obj文件。
aviit,

10

我只是在Visual Studio 2013中遇到了这个问题。显然,现在,在同一解决方案中拥有两个项目并设置依赖项还不够。您需要在它们之间添加项目参考。要做到这一点:

  1. 右键单击解决方案浏览器中的项目
  2. 单击添加=>引用...
  3. 单击添加新引用按钮
  4. 选中此项目所依赖的项目的框
  5. 点击确定

设置依赖项是什么意思?我添加了参考,但它仍然抱怨。devblogs.microsoft.com/cppblog/cpp-testing-in-visual-studio建议这样做就足够了。
tschumann '19


6

可以得到此链接器错误的另一种方式(就像我以前一样)是,如果要从dll 导出类的实例,但尚未将该类本身声明为import / export。

 #ifdef  MYDLL_EXPORTS 
    #define DLLEXPORT __declspec(dllexport)  
 #else
    #define DLLEXPORT __declspec(dllimport)  
 #endif

class DLLEXPORT Book // <--- this class must also be declared as export/import
{
public: 
    Book();
    ~Book();
    int WordCount();
};

DLLEXPORT extern Book book; // <-- This is what I really wanted, to export book object

因此,即使主要是我仅导出上述Book类的实例book,我也必须将该Book类声明为export / import类,否则book.WordCount()在其他dll中进行调用会导致链接错误。


2

这件事发生在我身上,所以我想我可以分享我的解决方案,就这么简单:

配置属性 -> 常规 -> 字符集中检查两个项目的字符集

我的UnitTest项目使用默认的字符集多字节,而我的库使用Unicode
我的功能是使用TCHAR作为参数。正如我的lib结果我TCHAR转化WCHAR但它是一个字符*我的单元测试:符号是不同的,因为参数是真的不到底相同。


1

我只是发现LNK2019如果忘记为类中的已声明函数提供定义,则会在Visual Studio 2015的编译过程中发生这种情况。

链接器错误是高度隐秘的,但是我通读错误来缩小缺少的内容,并在类外提供定义以清除此错误。


在某些情况下的问题是,包含类DEFS头都是很好的参考/包括在内,但可能不被其相应的CPPS 提供给连接器。最好的检查方法是在解决方案资源管理器中浏览项目外部依赖项。但是,对于VS发出关于该错误的某种文件存在/包含警告将是有益的。
Laurie Stearn'Mar

1

就我而言,在属性->常规中将cpp文件设置为“ C / C ++编译器”,即可解决LNK2019错误。



0

在Visual Studio 2017中,如果要测试公共成员,只需将真实项目和测试项目放在同一解决方案中,然后在测试项目中添加对真实项目的引用。

有关更多详细信息,请参见MSDN博客中的Visual Studio中的C ++单元测试。您还可以在Visual Studio中选中“ 针对C / C ++编写单元测试”,以及在Visual Studio中选中“ 针对C ++ 使用Microsoft单元测试框架”,后者是如果您需要测试非公共成员并且需要将测试放入同一项目中作为您的真实代码。

请注意,您要测试的内容将需要使用导出__declspec(dllexport)。有关更多详细信息,请参见使用__declspec(dllexport)从DLL导出

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.