2011-03-07 67 views
0

我收到以下错误 - errors每当我试图编译以下程序 - http://codepad.org/Bf9l8j9H在2010年VS如何解决以下错误?

任何想法如何解决这些错误?

+0

@ user597272:尝试以Unicode再次编译(进入属性,并设置为多字节) – fazo 2011-03-07 11:43:22

+0

thts bcoz我还没有accpted的答案是这仍然是尚未解决的相同的代码... – digster 2011-03-07 11:51:27

+0

@user:请不要张贴链接到代码。相反,创建一个**最小**工作示例(重现错误的示例)并直接在您的问题中发布。同样的错误 - 请不要截图,而是使用纯文本。 – 2011-03-07 12:00:52

回答

3

这是一个链接错误,它表明您已经宣告但尚未确定(或定义不链接)以下过载:

std::ostream& operator<<(std::ostream&, node<weight>&); 

常见的检查,从这里办将核查是否你有一个定义,该定义签名是否申报相匹配(你有没有宣布,但定义的运营商采取一个const引用?),定义是否被编译和链接...

我只是得到了一些时间并且实际上阅读了代码,我将基本上将其浓缩到:

template <typename T> 
struct node { 
    friend std::ostream& operator<<(std::ostream&, node<T>&); // [1] !!!! 
}; 
template <typename T> 
std::ostream& operator<<(std::ostream& o, node<T>& n) {} // [2] 

这是一个常见的错误,也是为什么它更简单的原因之一就是将模板中的朋友函数的定义与他们联系起来。基本上,在[1]模板被声明(和结交)非模板函数接受一个ostream&node<T>&对象。

的这里微妙之处在于,当模板实例为某些特定类型,并且friend声明被处理,T是固定的,并且该行协助一个自由非模板化的功能。例如,如果你实例nodeint,如node<int> n,编译器将注入int并用它代替T,那么friend声明将是:friend ostream& operator<<(ostream&, node<int>&),而这又声称,在该封闭命名空间的自由函数。制作该声明明确(并假设你只有int实例化的模板,你的代码被编译器作为阅读:

template <typename T> struct node { 
    friend ostream& operator<<(ostream&, node&); // [1] note <T> not required here 
}; 
// instantiating with int: 
ostream& operator<<(ostream&, node<int>&); // [3] declaration, not definition 

template <typename T> 
ostream& operator<<(ostream&, node<T>&) {} // [2] your definition 

在这一点上,只要您输入std::cout << a_int_node;编译器将考虑所有重载,它会找到一个非模板免费功能[3]这是一个完美的匹配,和模板化版本[2],但非模板版本为准。编译器不会实例化模板operator<<并期待您手动定义函数在一个翻译单元。

解决方案

最简单最好的解决办法是有编译器生成的免费功能为您服务。您只需提供模板类里面的运营商定义,一切都会好的和简单:

template <typename T> 
struct node { 
    friend std::ostream& operator<<(std::ostream& o, node& n) // [1] 
    { /* code goes here */ return o; } 
}; 

即使代码是因为friend在那里,你实际上声明和定义函数的模板中,在命名空间级别。如果您使用int实例化模板,则编译器将在封闭名称空间中为您生成:std::ostream& operator<<(std::ostream&, node<int>&)

这个解决方案是最好的:您只授予对单个代码段的访问权限,编译器会处理大部分血腥细节。

另一方面,你可以结交一个完整的模板函数。该语法是:

template <typename T> 
struct node { 
    template <typename U> 
    friend std::ostream& operator<<(std::ostream&, node<U>&); // [4] 
}; 
template <typename T> 
std::ostream& operator<<(std::ostream& o, node<T>& n) // can access private parts 
{ /* code goes here */ return o; } 

在这种情况下,您打开的node所有实例的模板功能,语义是开放类的其他用户的所有实例。

第三个选项是结交了一个模板实例化,这将具有与代替非模板免费功能,您使用的是模板化的一个唯一的区别第一个选项相同的效果。在另一方面,语法是相当比较繁琐,因为它需要结交之前声明函数模板,而这又需要声明类模板:

template <typename T> struct node;     // forward declare the class template 
template <typename T> 
std::ostream& operator<<(std::ostream&, node<T>&); // declare function template 
template <typename T> 
struct node {          // define class template 
    friend std::ostream& operator<< <>(std::ostream&, node<T>&); // befriend instantiation 
}; 
template <typename T> 
std::ostream& operator<<(std::ostream& o, node<T>& n) // define function template 
{ ... } 

正如你看到的,最简单的最好的解决办法是刚刚定义类定义中的函数模板。

+0

会发生什么......不知何故,它没有来我的通知,我已经尝试仔细研究它,但无济于事......所以我在这里发布它作为最后的手段..我知道什么是错的..但我希望有人首先注意它,并设法正确编译程序... – digster 2011-03-07 12:00:41

+2

正确的方法是找到应该定义它的.cpp文件,并检查它是否实际定义它。如果你让Visual Studio生成一个MAP文件,它告诉你所有函数的地址,你也知道这些函数实际上进入了.obj文件。 – MSalters 2011-03-07 12:51:22

+0

重载的运算符“<<”在上面的代码本身定义.... – digster 2011-03-07 15:21:56

0

CONIO.H是从MS-DOS的编译器的旧的头;更新:但它仍然在VS 2010中可用。

最好是你用过之后你宣布一个流。

+0

所以我现在应该做什么来解决它? – digster 2011-03-07 11:52:53

+0

是conio.h的替代方案吗? – digster 2011-03-07 12:02:20

+0

那么,我刚刚检查,看起来像我错了。实际上在VC2010中仍然可用。所以我为误导而道歉,但我没有看到这个很长时间以来使用过的东西。我想你正在使用它来调用_getch()。你可以用std :: cin替换它。但是,我可以包含并调用_getch()而没有任何问题。编译代码时遇到的唯一问题就是这段代码: 最佳<<(* p)。 – 2011-03-07 12:38:28