对解决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可以看这里,这个作者讲得非常细致。也希望我有一天能够变成这样的内容输出者。

写在结尾

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

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值