2010-10-28 33 views
0

我有一些错误代码的代码我不明白如何解决。我问过我的教授和助教,除了更准确地理解错误的含义外,没有运气就咨询了互联网。从我所知道的来看,编译器会让我的重载操作符与内置操作符混淆,或者它根本不认为它是一个重载操作符。关于C++模板上的重载操作符的一些编译错误

我收到以下错误和警告:

|| ===项目4项,调试=== | \ project 4 \ forest.h | 13 | warning:friend declaration'Forest & operator +(Forest &,Forest &)'声明了非模板函数|注意:(如果这不是你想要的,请确保函数模板已经被声明,并且在函数名称后面加上<>)|

\ project 4 \ forest.h | 13 |

\项目4 \ forest.h | 14 |警告:朋友宣言 '的std :: ostream的&操作< <(STD :: ostream的&,常量森林&)' 声明一个非模板函数|

\项目4 \ forest.h | 15 |警告:朋友宣言 '的std :: istream的&操作>>(的std :: istream的&,森林&)' 声明一个非模板函数|

\ project 4 \ main.cpp ||在函数'int main()'中: \ project 4 \ main.cpp | 21 | error:'文件>> intForest'中'操作符'的模糊重载|

c:\ program files(x86)\ codeblocks \ mingw \ bin .. \ lib \ gcc \ mingw32 \ 4.4.1 \ include \ C++ \ istream | 119 |注意:考生是:std :: basic_istream < _CharT ,_Traits> &的std :: basic_istream < _CharT,_Traits> ::运算>>(标准:: basic_istream < _CharT,_Traits> &(*)(标准:: basic_istream < _CharT,_Traits> &))[用_CharT =炭,_Traits = std :: char_traits] |

c:\ program files(x86)\ codeblocks \ mingw \ bin .. \ lib \ gcc \ mingw32 \ 4.4.1 \ include \ C++ \ istream | 123 | note:std :: basic_istream < _CharT,_Traits> &的std :: basic_istream < _CharT,_Traits> ::运算>>(标准:: basic_ios < _CharT,_Traits> &(*)(标准:: basic_ios < _CharT,_Traits> &))[用_CharT =炭,_Traits = std :: char_traits] |

c:\ program files(x86)\ codeblocks \ mingw \ bin .. \ lib \ gcc \ mingw32 \ 4.4.1 \ include \ C++ \ istream | 130 | note:std :: basic_istream < _CharT,_Traits> & std :: basic_istream < _CharT,_Traits> :: operator >>(std :: ios_base &(*)(std :: ios_base &))[with _CharT = char,_Traits = std :: char_traits] | || ===构建完成:1个错误,3个警告=== |

当我尝试编译我的代码。相关的代码段如下:

(在forest.h)

template< typename NODETYPE > class Forest 
{ 

    public: 
     friend Forest<NODETYPE>& operator+(Forest<NODETYPE>&, Forest<NODETYPE>&); 
     friend ostream& operator<<(ostream&, const Forest<NODETYPE>&); 
     friend istream& operator>>(istream&, Forest<NODETYPE>&); 

     Forest(); 
     Forest(const Forest& otherForest); 
     ~Forest(); 
     void nodes(int&) const; 

    private: 
     ForestNode<NODETYPE> *root; 

     ForestNode<NODETYPE> *getNewNode(const NODETYPE &); 
}; 

(在森林

。CPP)

template<typename NODETYPE> istream& operator>>(istream& file, const Forest<NODETYPE>& f1) 
{ 
    istream file2 = file; 
    int nodeCount = 0; 
    string blah = ' '; 

    while(getline(file2,blah)) 
    { 
     nodeCount++; 
    } 

    ForestNode<NODETYPE> *forestNodeArray[nodeCount];//holds pointers to last node of depth i 

    getline(file,*f1.root.tag); 
    forestNodeArray[0] = &(*f1.root); 
    inputHelper(file, 0, *f1.root, forestNodeArray, nodeCount); 

    return file; 
} 

(终于,在main.cpp中)

int main() 
{ 

    Forest <char> intForest(); 
    filebuf fb; 
    fb.open ("forest1.txt",ios::in); 
    istream file(&fb); 


    cout << typeid(intForest).name() << endl; 
    cout << typeid(file).name() << endl; 

    file >> intForest; 

    fb.close(); 


} 

任何帮助将不胜感激。

编辑:感谢亚历克斯和阿尔夫,我明白他们为什么不被视为模板功能。回想起来很明显,我只是设置了这些签名。无论如何,我仍然得到关于模糊运算符的错误。为什么编译器不能识别我的操作符并使用它,而不是试图在操作符的3个内置版本之间做出决定,这些操作符不可能有一个参数为Forest?

+0

尝试'模板<>朋友森林与运营商+' – 2010-10-28 05:28:13

+0

@alex啊。这解决了警告。谢谢。我有点希望声明保持原来的样子,这是由于我的教授给出的项目指南中指定的函数签名,但我开始越来越关注遵守这些函数签名和更多关于有工作代码。再次感谢。 – joedillian 2010-10-28 05:36:28

+0

好吧,如果你仔细想想,朋友函数的签名取决于你的模板参数'NODETYPE',所以它们也必须是模板。没有办法绕过它。 – 2010-10-28 16:32:29

回答

1

第二个错误是在这条线:

Forest <char> intForest(); 

这可能是起初令人惊讶,但该行并未声明Forest<char>类型的变量,而是一个不带参数并返回的函数。 刚刚从声明中删除括号:

Forest <char> intForest; 

在第一次警告,这已经是解释(声明为友元函数不是一个模板,这意味着你将必须手动实现它为每种类型你可以用Forest<>来实例化(可能你不想这么做)。还要注意声明模板operator+,然后把模板变成朋友,就像@Alf P. Steinbach的回答意味着Forest<int>将会是Forest<double>的朋友,这可能不是你所需要的。@Alex提议在评论中只会将模板的特定实例化成一个朋友,这可能更接近你想要的,但是你需要声明模板操作模板类之前,以及您需要转发声明模板类...

在模板朋友免费功能的一个常见的模式是定义函数的地方:

template <typename T> 
class Forest { 
    // ... 
    friend Forest& operator+(Forest const & lhs, Forest const & rhs) [1] 
    { 
     // implementation here 
    } 
} 
// [1] Note that the arguments are const references (read only), and also note that 
//  you do not need to provide the type argument inside the template declaration 

这允许您将其定义为非模板化函数,同时让编译器为您实例化该函数。此外,在处理模板时定义类定义中内联的成员方法通常也更简单。它使生活变得更简单,毕竟在大多数情况下,您确实需要在(相同的)头文件中提供实现。

但是,在定义二元运算符时,更好的方法是将operator+=定义为成员方法,然后可以很容易将operator+定义为非友元函数。该模式将是:

struct test { 
    test& operator+=(test const &); 
}; 
test operator+(test lhs, test const & rhs) { // [2] 
    lhs += rhs; 
    return lhs; 
} 
// [2] Note that the first argument is by value, and the second by const reference 
//  This means that the compiler will copy the first argument for you, and you 
//  are free to modify it with the += operator and return the copy. 

现在,最棘手的部分是混合前两个建议。为了能够定义operator+该模板定义范围内的免费功能,常用的伎俩是让朋友即使不需要访问的原因:

template <typename T> 
class Forest { 
    Forest& operator+=(Forest const &) { 
     // implemenation 
    } 
    friend Forest operator+(Forest lhs, Forest const & rhs) { // [3] 
     return lhs+=rhs; 
    } 
}; 
// [3] friendship only to allow us to define the free function inside the template 
//  declaration. 
+0

是的,我认为这很奇怪。我的班级助教添加了那些()我已经按照你的建议。现在你说出它的实际含义了,这非常明显。无论哪种方式,我仍然有一系列的错误,基本上说它不能识别我的超载>>操作符。下面是一个示例: \ project 4 \ main.cpp | 21 |错误:'文件>> intForest'中的'operator >>'不匹配。 c:\ program files(x86)\ codeblocks \ mingw \ bin \ .. \ lib \ gcc \ mingw32 \ 4.4.1 \ include \ C++ \ istream | 119 |注意:应该是:std :: basic_istream <_CharT ,_Traits>&std :: basic_istream <_CharT,_Traits> :: operator >> ... – joedillian 2010-10-28 08:02:45

+0

然后继续列出basic_istream类中的>>运算符的每个实例。 – joedillian 2010-10-28 08:06:48

+0

我无法在编译器列出的三个候选人中找到我的头。 – Chubsdad 2010-10-28 08:13:03

0

(第一次)警告告诉你友好函数不是模板。

而事实并非如此。

想想你将如何实现它。这需要为每个可能的NODE_TYPE编写一个这样的函数。

有几种方法可以解决这个问题。

的一种方法是去亲近一个函数模板,如下所示:。

template< class Type > 
struct S 
{ 
    template< class U > friend void foo(S<U>); 
}; 

template< class Type > 
void foo(S<Type> x) {} 

int main() 
{} 

干杯& HTH,

+0

谢谢alf。你和alex明确说明了做这些事情的正确语法,我的Dietel参考资料没有任何通用朋友函数的例子。如果你可能想知道为什么C++会把我的>>操作符和内建在istream中的操作符混淆起来,那会很好,但是感谢你给的帮助。 – joedillian 2010-10-28 05:48:02

0

学习C++,我也遇到了同样的问题但我以另一种方式解决了它!

template <class NODETYPE> class Forest; 
template <class NODETYPE> Forest<NODETYPE>& operator+ (Forest<NODETYPE>&, Forest<NODETYPE>&); 
template <class NODETYPE> ostream& operator<<(ostream&, const Forest<NODETYPE>&); 
template <class NODETYPE> istream& operator>> (istream&, Forest<NODETYPE>&); 
template<class NODETYPE> 
template< typename NODETYPE > 
class Forest 
{ 

    public: 
     friend Forest<NODETYPE>& operator+ <>(Forest<NODETYPE>&, Forest<NODETYPE>&); 
     friend ostream& operator<< <>(ostream&, const Forest<NODETYPE>&); 
     friend istream& operator>> <>(istream&, Forest<NODETYPE>&); 

     Forest(); 
     Forest(const Forest& otherForest); 
     ~Forest(); 
     void nodes(int&) const; 

    private: 
     ForestNode<NODETYPE> *root; 

     ForestNode<NODETYPE> *getNewNode(const NODETYPE &); 
};