对解决Visual Studio的 LNK2019 和 LNK1120 错误的一点经验

2 篇文章 0 订阅
1 篇文章 1 订阅

对解决Visual Studio的 LNK2019 和 LNK1120 错误的一点经验

问题描述

写了一个 text searching 的代码。该代码设计了数个类,并有一个 interface class 通过指向 base class 的 shared_ptr 通过 dynamic binding 来运行。然而结构设计的不是特别好,这也就导致我遇到了下面的问题:

interface class header file:

std::ostream &operator<<(std::ostream &, const QueryResult &);

interface class source file

std::ostream &operator<<(std::ostream &os, const QueryResult &query) {
	// details
}

base class header file, which is included by interface class header file

class QueryResult {
		//下面的语句是错误来源
		friend inline std::ostream &operator<<(std::ostream &, const QueryResult &);
		//details
}

接着在尝试运行时就发现了 LNK2019LNK1120 错误。以下为错误描述:

无法解析的外部符号 “class std::basic_ostream<char,struct std::char_traits > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits > &,class QueryResult const &)” (??6@YAAEAV? b a s i c o s t r e a m @ D U ? basic_ostream@DU? basicostream@DU?char_traits@D@std@@@std@@AEAV01@AEBVQueryResult@@@Z),函数 main 中引用了该符号

尝试分析

根据错误描述,可以锁定错误出自上面的第一行代码。Visual Studio给出的错误是无法解析,这样一个错误描述有些宽泛,放到 dev cpp 里就会好得多,它的错误提示长下面这样子:

[警告] inline 函数 ‘std::ostream& 运算符<<(std::ostream&, const QueryResult&)’ used but never defined

然而我一开始并没有用 dev ,而是自己看 web 调了半天,还找了我的两个同学帮我看了一下。他们的解决方案是把 source file 给 include 进来(这也让我有点吃惊,为什么大二的计科同学会没有 package 的概念)。这样的方案我显然没办法满意,我无法理解,为什么编译器会找不到一个已经 declarated 并且 defined 的函数。出于这种疑惑,我友善地提醒了一下编译器——产生了我的第一个解决方案:

interface class header file:

extern std::ostream &operator<<(std::ostream &, const QueryResult &);

不得不说vs的 MSVC 编译器是真的强大,加个 extern 就能联想到同名的inline函数。如果我没有写这个blog的话,我也许会沾沾自喜于这个解决方案并且依然想破头皮都想不明白为什么会出现这种错误。直到我为了验证这个错误用 dev 上又跑了一遍。我的 dev 编译器是 g++ (版本我也不是很清楚,小白都是一键装环境的),没有这么智能,很实诚地提醒了我。由于 operator<< 函数需要调用 QueryResult object 的 members ,再加上这个函数最开始是在base_Query.h 里 declarated 的,且我的 Query.h has included the base_Query.h,所以编译器找到了 inline 版本的 declaration ,而很不幸,这个函数我没有定义。于是,我得到了第二个解决方案:

base class header file, which is included by interface class header file

class QueryResult {
		//该文件前面的 declaration 也要改
		friend std::ostream &operator<<(std::ostream &, const QueryResult &);
		//details
}

顺便提一下我的下一个问题:为什么我会在 base_Query.h 里加上 inline 并且在后面的文件里忘记呢?

此事说来话长。我的C++是从《C++ Primer》入门的。在这本书里, Lippman 很细致地讲述了 inline 的作用(也就是没啥作用),但他的示例代码里还是会习惯性地带上 inline ,这个习惯也影响到了我。事实上,我原来的 source file 里全部加了 inline declaration ,这使得我一开始遇到的错误比现在多得多——也同样因为这个原因,我只有将 interface class source file 也 include 进来才能工作。后来一个同学在 STFW (Searching The Fucking Web)后告诉我分离式编程不能使用 inline 。然后这个函数是唯一一个声明了两次的函数,所以被我忘记了(笑)。

关于为什么分离式编程不能使用inline可以看这里,这个作者讲得非常细致。也希望我有一天能够变成这样的内容输出者。

写在结尾

如果这篇文章对你有帮助,不要忘了帮我点个赞~你的赞是我更新的最大动力。

Visual Studio中修复LNK2019错误通常涉及以下几个步骤: 1. **检查main函数**: 确保您的主入口点(main函数)已经被正确地定义声明。如果你是新手,main函数应该像下面这样简单: ```cpp int main() { // 应该有实际的代码逻辑 return 0; } ``` 2. **查看项目设置**: 检查项目属性(Project Properties),在"Configuration Properties" -> "Linker" -> "Input" -> "Additional Dependencies"项,确保已经包含了必要的库,例如对于C++项目,可能需要`mfc.lib`, `user32.lib`, 或者`mingw32.lib`等。 3. **添加main函数到源文件**: 如果你在自定义的库或者其他模块里找到了`invoke_main`,确保在适当的位置包含了main函数的实现,并且正确引用它。如果`invoke_main`不是标准库的一部分,可能需要将它的实现复制回项目的源文件中。 4. **更新库依赖**: 确认你的工程是否正确链接到了包含main函数实现的库。如果是在第三方库中,确保正确配置了库的导入链接过程。 5. **清理并重建项目**: 清理项目(Build > Clean Solution)然后重新构建(Build > Build Solution)看看问题是否解决了。 6. **错误排查**: 如果以上都没问题,可能需要检查是否有其他代码修改导致main函数不再可见,比如引入了新的命名空间或模块,导致原本隐式可见的main函数现在被遮蔽了。 记住,每种情况都可能有所不同,因此按照上述步骤逐一检查有助于定位解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值