函数定义在 cpp 文件中时的链接器错误

Posted

技术标签:

【中文标题】函数定义在 cpp 文件中时的链接器错误【英文标题】:Linker error when function definition is in cpp file 【发布时间】:2015-07-04 22:42:48 【问题描述】:

我的解决方案包含三个项目:GoogleTest(用于使用 Google Test)、Vi(用于大部分逻辑)和 ViTests(用于使用 Vi 的单元测试)。 ViTests 项目引用 Vi 项目和 Google Test 项目。

Vi在v1.h中有如下代码

#pragma once

namespace Vi

    class Vi1
    
    public:
        int SomeInt();
    ;

以及匹配的 v1.cpp

#include "vi1.h"

namespace Vi

    int Vi1::SomeInt()
    
        return 123;
    

ViTests 中的测试函数如下

TEST(Vi1Foo, SomeIntIsSame)

    Vi1 v = Vi1;
    EXPECT_EQ(123, v.SomeInt());

链接器错误表明存在未解析的符号SomeInt。但是,我可以通过像这样内联函数来消除链接器错误:

namespace Vi

    class Vi1
    
    public:
        int SomeInt()  return 123; 
    ;

为什么将单元测试项目放在单独的 cpp 文件中时找不到 SomeInt 函数定义?

谢谢。

额外的细节以防有用:我使用的是 Visual Studio 2015。

错误信息:

Error   LNK2019 unresolved external symbol "public: int __thiscall Vi::Vi1::SomeInt(void)" (?SomeInt@Vi1@Vi@@QAEHXZ) referenced in function "private: virtual void __thiscall ViTests::Vi1Foo_SomeIntIsSame_Test::TestBody(void)" (?TestBody@Vi1Foo_SomeIntIsSame_Test@ViTests@@EAEXXZ) Vi_Tests    C:\Users\MyName\Vi\Vi_Tests\Vi_Tests.obj    1

项目类型: Vi 是 Win32 应用程序,ViTests 是 Win32 控制台应用程序,GoogleTest 是一个静态库。

【问题讨论】:

您是否使用函数定义链接到文件? 我不明白你的意思。我应该在“附加依赖项”列表中包含 cpp 文件名吗? 如何链接到带有函数定义的文件? 是的,你可能会,但我以前从未使用过 VS 我不确定 C++ Win32 控制台项目(如 ViTests)引用 C++ Win32 应用程序项目(如 Vi)意味着什么。 ViTests 需要链接到 V1.obj - 直接作为目标文件,或间接通过以 V1.obj 为成员创建的静态库。我不确定引用 Win32 应用程序项目是否会做这些事情。我认为您需要将V1.obj(可能还有其他目标文件)作为输入文件添加到ViTests 项目中的链接器。 【参考方案1】:

我在一个愚蠢的错误假设下工作。我假设 VS 只会拾取 cpp 文件,因为我引用了包含它们的项目并包含正确的头文件,但事实并非如此。

nabijaczleweli 说我应该链接“指向带有函数定义的文件”。在网上浏览了一番后,我发现了如何做到这一点。我发现this 发布了一个解决方案。 cpp 文件本身必须添加到测试项目中。这是通过右键单击 ViTests,选择“添加现有文件”并选择 vi1.cpp 来完成的。

这可行,但我对这个解决方案非常不满意,因为我必须根据需要添加这些文件。我发现我可以解决这个问题,将项目 Vi 的类型更改为静态库。这被描述为here。 Michael Burr 的评论描述了一种链接到目标文件的方法,该方法也可以使用。

如果没有这个帖子中的海报的帮助,我不会这么快就明白这一点。非常感谢大家。

【讨论】:

【参考方案2】:

您没有指定项目的类型。我猜它们是 DLL,因此您希望在它们之外使用的非内联函数或类需要导出:在源代码中声明为 __declspec(dllexport) 或在 DEF 文件中列出。

如果您使用 __declspec(dllexport),请记住 __declspec(dllimport) 使用项目中的函数。这通常通过在 .h 文件中用作限定符的宏来实现,该宏在不同项目中的解析方式不同。

【讨论】:

但它不必知道该方法属于哪个类吗?无论如何我尝试删除它,但错误仍然存​​在。但是谢谢你的想法:) 我的错 - 我错过了 Vi1 中的“1”。即将删除答案 我没有考虑过项目类型。我将更新我的答案以包含此信息,因为我认为它可能很有希望。

以上是关于函数定义在 cpp 文件中时的链接器错误的主要内容,如果未能解决你的问题,请参考以下文章

链接器错误:未定义的函数引用

链接器如何知道两个源文件中哪个是主文件,另一个包含函数定义?

关于一个多个.cpp文件的项目中,函数出现未定义引用错误

在命名空间内定义函数时引发链接器错误? [复制]

链接器在命名空间中找不到函数定义

链接阶段的多重定义错误