本文介绍了为什么选择LNK1120& LNK2019出现在模板和朋友功能的情况下的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我编译了第一个版本的代码在Turbo-C,它编译没有任何错误。但是当我在Visual Studio或普通的g ++从CommandLine编译这个,我得到的错误提到在帖子。 I have compiled the first version of code in Turbo-C and it compiles without any error. But when I compile this in Visual Studio or plain g++ from CommandLine, I get errors mentioned down in the post. 我在互联网上搜索过,并读了一些StackOverflow的问题& MSDN LNK1120问题文档。我找到了一种方法来修复下面的代码。但是,没有清楚的理由。如何只是一个定义摆脱那个错误。在语法上,错误倾向的代码也看起来很好。 I did searched over internet and read some of the StackOverflow questions & MSDN LNK1120 problem docs. I found a way to fix the below code. However, didn't got the reason clearly. How can just a definition gets rid of that error. Syntactically the error prone code also look fine. 1) Error 2 error LNK1120: 1 unresolved externals 2) Error 1 error LNK2019: unresolved external symbol "void __cdecl totalIncome(class Husband<int> &,class Wife<int> &)" (?totalIncome@@YAXAAV?$Husband@H@@AAV?$Wife@H@@@Z) referenced in function _main 注意:请注意箭头程序中。我明确把它们。 Note: Please watch out for arrows in program. I've explicitly put them. So, might not go through the complete program. 错误代码: #include <iostream>using namespace std;template<typename T> class Wife; // Forward declaration of template template<typename T> class Husband{ friend void totalIncome(Husband<T> &hobj, Wife<T> &wobj); public: Husband() = default; Husband(T new_salary): salary{new_salary} {} private: T salary; };template<typename T> class Wife{ friend void totalIncome(Husband<T> &hobj, Wife<T> &wobj); public: Wife() = default; Wife(T new_salary): salary{new_salary} {} private: T salary; };template<typename T> void totalIncome(Husband<T> &hobj, Wife<T> &wobj) __{ | cout << "Total Income of Husband & Wife: "; | cout << hobj.salary + wobj.salary; |} | ---int main(){ Husband<int> h(40000); Wife<int> w(90000); totalIncome(h, w); return 0;}但在下面的情况下,运行完美。为什么会是什么原因? but in the below case by just moving the definition up in the class, it runs perfectly fine. Why whats the reason? 固定代码:#include <iostream>using namespace std;template<typename T> class Wife; // Forward declaration of template template<typename T> class Husband{ friend void totalIncome(Husband<T> &hobj, Wife<T> &wobj); public: Husband() = default; Husband(T new_salary): salary{new_salary} {} private: T salary; };template<typename T> class Wife{ friend void totalIncome(Husband<T> &hobj, Wife<T> &wobj) __ { | cout << "Total Income of Husband & Wife: "; | -- definition moved up here cout << hobj.salary + wobj.salary; | } __| public: Wife() = default; Wife(T new_salary): salary{new_salary} {} private: T salary; };/*template<typename T> void totalIncome(Husband<T> &hobj, Wife<T> &wobj) __{ | cout << "Total Income of Husband & Wife: "; | cout << hobj.salary + wobj.salary; |} | ---*/int main(){ Husband<int> h(40000); Wife<int> w(90000); totalIncome(h, w); return 0;} 推荐答案到一个最小的例子,再现问题:First, let's cut this down to a minimal example that reproduces the issue:template<typename T> class Husband{ friend void totalIncome(Husband<T> &); };template<typename T> void totalIncome(Husband<T> &hobj){}int main(){ Husband<int> h; totalIncome(h);}这会导致类似的链接器错误。例如,使用clang ++:This leads to a similar linker error. For example, using clang++:/tmp/main-fb41c4.o: In function `main':main.cpp:(.text+0xd): undefined reference to `totalIncome(Husband&)' 基本问题与模板上的重载算术运算符导致未解决的外部错误以及模板运算符<< 的异常行为。 The underlying issue is the same as the one in Overloaded arithmetic operators on a template causing an unresolved external error and in Strange behavior of templated operator<<. Hence, I'll base my answer here on my answer from the second question.在类模板 Husband 中,有一个朋友声明函数 totalIncome :In the class template Husband, there is a friend-declaration of the function totalIncome:friend void totalIncome(Husband<T> &); ),直到并包括最内层的命名空间。如果找到了该名称的声明,则声明的实体将结成友谊:A friend function declaration looks up the name of the declared function (here: totalIncome) in the surrounding scopes up to and including the innermost enclosing namespace. If a declaration of that name is found, the declared entity is befriended:class Husband;void totalIncome(Husband&); // (A)class Husband{ friend void totalIncome(Husband&); // befriends (A)};如果没有找到名称的声明,命名空间::If no declaration of the name is found, a new function is declared in the innermost enclosing namespace:class Husband{ friend void totalIncome(Husband&); // declares and befriends ::totalIncome};void totalIncome(Husband&); // friend of class Husband如果函数只通过friend函数声明If the function is only declared via the friend function declaration (and there is no later declaration in the enclosing namespace), the function can only be found via Argument-Dependent Lookup. OP的代码中的问题是涉及到一个类模板:The issue in the OP's code is that there is a class template involved:template<typename T> class Husband{ friend void totalIncome(Husband<T> &); };规则保持不变:没有声明 totalIncome 。由于朋友声明的签名取决于类模板的模板参数, Husband 的每个实例将在封闭命名空间中引入一个新函数 。 (如果朋友声明不依赖于模板参数,您将会在 Husband 的每个实例化中获得一个重新声明。)例如,如果你实例化 Husband< int> 和 Husband< double> ,你将在全局命名空间中得到两个函数: / p> The rules stay the same: No declaration of totalIncome is found. Since the signature of the friend declaration depends on the template parameter of the class template, every instantiation of Husband will introduce a new function in the enclosing namespace. (If the friend declaration did not depend on a template parameter, you'd get a redeclaration with every instantiation of Husband.) For example, if you instantiate Husband<int> and Husband<double>, you'll get two functions in the global namespace:void totalIncome(Husband<int> &);void totalIncome(Husband<double> &);请注意,这些是两个不相关的函数,很像:Note that these are two unrelated functions, much like:void totalIncome(int &);void totalIncome(double &); 使用函数模板重载函数 您可以使用函数模板重载普通函数:Overloading a function with a function templateYou can overload an "ordinary" function with a function template:void totalIncome(Husband<int> &); // (A)template<typename T> void totalIncome(Husband<T> &); // (B) 当通过 Husband< int> X; totalIncome(x); ,函数模板将产生一个实例:When calling the function via Husband<int> x; totalIncome(x);, the function template will produce an instantiation:void totalIncome<int>(Husband<int> &); // (C), instantiated from (B)并且你的重载集合包含两个函数: / p> And your overload set consists of two functions:void totalIncome(Husband<int> &); // (A)void totalIncome<int>(Husband<int> &); // (C)一切都相等,重载分辨率会更喜欢非模板函数通过函数模板专门化(C)。All things equal, overload resolution will prefer the non-template function (A) over the function template specialization (C).这是在OP的代码中发生的:还有一个非模板函数引入了实例化类模板 Husband 和一个无关的函数模板。重载解析选择非模板函数,并且链接器声明它没有定义。And this is what happens in the OP's code as well: There is a non-template function introduced by instantiating the class template Husband, and an unrelated function template. Overload resolution chooses the non-template function, and the linker complains that it doesn't have a definition.最简单的解决方法是在类定义中定义friend函数:The simplest solution is to define the friend function inside the class definition:template<typename T> class Husband{ friend void totalIncome(Husband<T> &){ // code here } }; 使用前向声明的解决方案:A solution using forward-declarations:template<typename T> class Husband;template<typename T> void totalIncome(Husband<T> &);template<typename T> class Husband{ friend void totalIncome(Husband<T> &); };template<typename T> void totalIncome(Husband<T> &hobj){}可以找到前向声明的函数模板并且对其进行专门化,而不是声明新的函数。可能值得明确添加模板参数:Here, the compiler can find the forward-declared function template and befriend a specialization of it, instead of declaring a new function. It might be worthwhile explicitly adding the template arguments:template<typename T> class Husband{ friend void totalIncome<T>(Husband<T> &); };由于此强制 code> totalIncome 。Since this enforces that there is a prior declaration of the function template totalIncome. p> A solution befriending the whole function template:template<typename T> class Husband{ template<typename U> friend void totalIncome(Husband<U> &); };template<typename T> void totalIncome(Husband<T> &hobj){} 函数模板,以及在类定义重命名之后的命名空间范围的后声明,并定义了此函数模板。函数模板的所有专业化将与 Husband 的所有实例相关。In this solution, the friend-declaration declares a function template, and the later declaration at namespace scope following the class' definition redeclares and defines this function template. All specializations of the function template will be befriended by all instantiations of Husband. 这篇关于为什么选择LNK1120& LNK2019出现在模板和朋友功能的情况下的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 10-28 09:38