【模板友元函数】菜鸟提问

时间:2022-09-30 23:29:38
我的头文件中是类模板和函数
#ifndef Node_H
#define Node_H
template<typename T>
class Node
{
public:
Node( int =0 );
Node( const Node& );
~Node();
friend istream& operator>> ( istream&, Node<T>& );
friend ostream& operator<< ( const ostream&, const Node& );
protected:
Node* next;
T number;
};


其中友元函数代码


template<typename T>
istream& operator>> ( istream& input, Node<T>& temp )
{
Node *p = temp.next;
for( cin>>temp.number; p!=NULL; p=p->next )
cin >> p->number;
return input;
}
template<typename T>
ostream& operator<< ( const ostream& output, const Node<T>& temp )
{
Node *p = next; 
for( cout << number; p!=NULL; p=p->next )
cout << " -> " << number;
return output;
}



main函数
#include<iostream>
#include<ctime>
using namespace std;
#include"myList.h"

int main()
{
Node<int> a(5);
cin >> a;
cout << a;
}



出错信息


1>main.obj : error LNK2019: 无法解析的外部符号 "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > const &,class Node<int> const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@ABV01@ABV?$Node@H@@@Z),该符号在函数 _main 中被引用
1>main.obj : error LNK2019: 无法解析的外部符号 "class std::basic_istream<char,struct std::char_traits<char> > & __cdecl operator>>(class std::basic_istream<char,struct std::char_traits<char> > &,class Node<int> &)" (??5@YAAAV?$basic_istream@DU?$char_traits@D@std@@@std@@AAV01@AAV?$Node@H@@@Z),该符号在函数 _main 中被引用



谢谢啊

17 个解决方案

#1


1.将友元函数的实现放到类里面去。
2.或者将声明改为:
  template<class S>  friend istream& operator>> ( istream&, Node<S>& );
  template<class S> friend ostream& operator<< ( const ostream&, const Node<S>& );

#2


引用 1 楼 pengzhixi 的回复:
1.将友元函数的实现放到类里面去。
2.或者将声明改为:
  template<class S> friend istream&amp; operator>> ( istream&amp;, Node<S>&amp; );
  template<class S> friend ostream&amp; operator<< ( const ostream&amp;, const Node<S……



up++




********************************************************************************
*  C++经典之作下载链接: http://blog.csdn.net/jerryjbiao/article/details/7358796 *
********************************************************************************

#3


友元函数要先在类模板Node前面声明,在声明友元函数之前,还要先进行类模板Node的声明,
friend ostream& operator<< ( const ostream&, const Node& );这一条语句的第二个函数参数Node是类模板,不是类,改为:const Node<T> &
Node* next; 这一条语句也有错,Node是类模板,不是类,改为:Node<T> *next;

你的头文件中的代码修改如下:

#ifndef Node_H
#define Node_H

#include <iostream>
using std::istream;
using std::ostream;

template<Typename T>
class Node;

template<Typename T>
istream &operator >>(istream &,Node<T> &);

template<Typename T>
ostream &operator <<(ostream &,const Node<T> &);

template<Typename T>
class Node
{
 public:
 Node( int =0 );
    Node( const Node& );
    ~Node();
friend istream &operator >> <>(istream &,Node<T> &);
friend ostream &operator << <>(ostream &,const Node<T> &);

protected:
    Node<T> *next;
    T number;
};


下面是友元函数的定义:


template<Typename T>
istream &oprator >> <>(istream &input, Node<T> &temp)
{
Node *p = temp.next;
    for( cin>>temp.number; p!=NULL; p=p->next )
        cin >> p->number;
    return input;
}

ostream &operator << <>(ostream &output,const Node<T> &temp)
{
Node *p = next; 
    for( cout << number; p!=NULL; p=p->next )
        cout << " -> " << number;
    return output;

}

#4


引用 1 楼 pengzhixi 的回复:
1.将友元函数的实现放到类里面去。
2.或者将声明改为:
  template<class S>  friend istream&amp; operator>> ( istream&amp;, Node<S>&amp; );
  template<class S> friend ostream&amp; operator<< ( const ostream&amp;, const Node……


额,,那个S代表我定义的类Node?,,我还试了就字母S,就是不行啊,,具体说按我原来的代码怎么改呢,,谢谢

#5


按我的改,可以运行的

#6


你还要实现类模板Node的构造函数,在main函数所在的源文件中实现,其代码如下:


template<typename T>
Node<T>::Node( int n = 0):number(n)
{}

#7


引用 5 楼 lou0378 的回复:
按我的改,可以运行的



额,,刚改完,,和你一模一样除了在第二个函数定义时,多个 template<typename T>外,,,但问题还是一样。。

如果去掉那句,,问题更多

#8


你把头文件的名字写出来:然后把头文件里的代码全部贴出来,
然后再把类模板的定义和友元函数的定义所在的文件名字写出来,把源文件的全部代码贴出来

再帮你改

#9


Node *p = temp.next;
    for( cin>>temp.number; p!=NULL; p=p->next )
        cin >> p->number;
你友元函数中的代码有问题,比如:Node *p = temp.next;都没为指针p分配空间,就使用了,按照我的改,模板格式是没错的

#10


引用 9 楼 lou0378 的回复:
Node *p = temp.next;
    for( cin>>temp.number; p!=NULL; p=p->next )
        cin >> p->number;
你友元函数中的代码有问题,比如:Node *p = temp.next;都没为指针p分配空间,就使用了,按照我的改,模板格式是没错的



好吧,,麻烦了



//typename_Node.h

#ifndef Node_H
#define Node_H

#include<iostream>
using namespace std;

using std::istream;
using std::ostream;

template<typename T>
class Node;

template<typename T>
istream &operator >>( istream &,Node<T> &);

template<typename T>
ostream &operator <<( ostream &,const Node<T> &);

template<typename T>
class Node
{
public:
Node( int =0 );
Node( const Node& );
~Node();
friend istream& operator>> ( istream&, Node<T>& );
friend ostream& operator<< ( ostream&, const Node<T>& );
protected:
Node<T> *next;
T number;
};

template<typename T>
Node<T>::Node(  int length )
{
if( length <= 0 )  
{
cout << "length wrong ! ";
exit(0);      
}
Node* p = next = NULL;
number = 0;
for( int i=1; i<length; i++ )
{
p = new Node;
p->number = 0;
p = p->next;
}
p = NULL;
}
template<typename T>
Node<T>::Node( const Node& mylist )
{
if( mylist.next == NULL )
{
next = '\0';
number = 0;
return ;
}
Node *p1, *p2;
number = mylist.number;
p1 = next;
p2 = mylist.next
while( p2!=NULL )
{
p1->number = p2->number;
p1 = p1->next;
p2 = p2->next;
}
}
template<typename T>
Node<T>::~Node()
{
number = 0;
if( next==NULL )
return;
for( Node* p = next; p !=NULL; p = next )
{
next = next->next;
delete p;
}
}
template<typename T>
istream &operator>> <>( istream &input, Node<T> &temp )
{
Node *p = temp.next;
for( cin>>temp.number; p!=NULL; p=p->next )
cin >> p->number;
return input;
}
template<typename T>
ostream &operator<< <>( ostream &output, const Node<T> &temp )
{
Node *p = next; 
for( cout << number; p!=NULL; p=p->next )
cout << " -> " << number;
return output;
}
#endif

#11


引用 9 楼 lou0378 的回复:
Node *p = temp.next;
    for( cin>>temp.number; p!=NULL; p=p->next )
        cin >> p->number;
你友元函数中的代码有问题,比如:Node *p = temp.next;都没为指针p分配空间,就使用了,按照我的改,模板格式是没错的


我构造函数里的int是要建立链表的长度,,不是里面的数number大小。

我还准备重载[]的,,可以像数组那样使用的,,不过我自己看书太模糊。。。谢啦

#12


上面是你用到的头文件,你的源文件的代码呢,也贴出来,不然的话,头文件的代码修改了,源文件的代码没改,没保持一致也会编译错误的

#13


按照下面的修改,编译是没问题的,也就是语法和格式是正确的,至于功能的实现,要把代码全部贴出来才能知道,不知你用的是什么编译器,我用的是VS2008的编译器。

头文件的代码修改如下:


//typename_Node.h

#ifndef Node_H
#define Node_H

#include <iostream>

using std::ostream;
using std::istream;
using std::cin;
using std::cout;

template<typename T>
class Node;

template<typename T>
istream &operator >>( istream &,Node<T> &);

template<typename T>
ostream &operator <<( ostream &,const Node<T> &);

template<typename T>
class Node
{
public:
    Node( int =0 );
    Node( const Node<T>& );
    ~Node();
    friend istream& operator>> <>( istream&, Node<T>& );
    friend ostream& operator<< <>( ostream&, const Node<T>& );
protected:
    Node<T> *next;
    T number;
};

template<typename T>
Node<T>::Node(  int length = 0 )
{
    if( length <= 0 )  
    {
        cout << "length wrong ! ";
        exit(0);      
    }
    Node* p = next = NULL;
    number = 0;
    for( int i=1; i<length; i++ )
    {
        p = new Node;
        p->number = 0;
        p = p->next;
    }
    p = NULL;
}
template<typename T>
Node<T>::Node( const Node<T>& mylist )
{
    if( mylist.next == NULL )
    {
        next = '\0';
        number = 0;
        return ;
    }
    Node *p1, *p2;
    number = mylist.number;
    p1 = next;
    p2 = mylist.next
    while( p2!=NULL )
    {
        p1->number = p2->number;
        p1 = p1->next;
        p2 = p2->next;
    }
}
template<typename T>
Node<T>::~Node()
{
    number = 0;
    if( next==NULL )
        return;
    for( Node* p = next; p !=NULL; p = next )
    {
        next = next->next;
        delete p;
    }
}
template<typename T>
istream &operator>> <>( istream &input, Node<T> &temp )
{
    Node *p = temp.next;
    for( cin>>temp.number; p!=NULL; p=p->next )
        cin >> p->number;
    return input;
}
template<typename T>
ostream &operator<< <>( ostream &output, const Node<T> &temp )
{
    Node *p = next; 
    for( cout << number; p!=NULL; p=p->next )
        cout << " -> " << number;
    return output;
}

#endif

#14


引用 13 楼 lou0378 的回复:
按照下面的修改,编译是没问题的,也就是语法和格式是正确的,至于功能的实现,要把代码全部贴出来才能知道,不知你用的是什么编译器,我用的是VS2008的编译器。

头文件的代码修改如下:

C/C++ code

//typename_Node.h

#ifndef Node_H
#define Node_H

#include <iostream>

using std::ostream……



感谢啊,,我把一些其他毛病改过后,,差不多了,,但是析构有点问题。。不明白,,感觉很对啊。。

帮忙看下啊


template<typename T>
Node<T>::~Node()
{
number = 0;
for( Node* p = next; p !=NULL; p = next )
{
next = next->next;
delete[] p;
}
}



可以输入输出,,但是最后会有问题。。改为delete p;也不行

如果没有析构,,让计算机析构就没有问题了

我的cpp

//main.cpp
#include<iostream>
#include<ctime>
using namespace std;
#include"myList.h"

int main()
{
Node<int> a(5);
cin >> a;
cout << a;
}

其中#include<ctime>是为以后功能准备的,,可以忽视

再次感谢啊

#15


你想实现的功能是不是建立一个单链表啊?但你的构造函数有问题的,看下面的这个循环;
 for( int i=0; i<length; i++ )
    {
        p = new Node;
        p->number = i;
        p = p->next;
    }
第一个循环是,你的传递的参数length是5,可以执行,但当第二次循环时,执行到P =new Node是,又会调用构造函数,而且使用的默认值,此时length = 0;就会执行exit(0);推出循环,你需要修改构造函数和析构函数

#16


不知道到底你的程序想实现什么功能?说具体点,你想干什么

#17


引用 16 楼 lou0378 的回复:
不知道到底你的程序想实现什么功能?说具体点,你想干什么


嗯,,就是有这个问题呢。。

我就是想建立一个单链表,,然后会加上其他功能。。

好吧,,已经都麻烦你了,,剩下的我自己搞定吧。。对于类模板中重载输入输出,我已经查到一些资料了。。

太感谢了

#1


1.将友元函数的实现放到类里面去。
2.或者将声明改为:
  template<class S>  friend istream& operator>> ( istream&, Node<S>& );
  template<class S> friend ostream& operator<< ( const ostream&, const Node<S>& );

#2


引用 1 楼 pengzhixi 的回复:
1.将友元函数的实现放到类里面去。
2.或者将声明改为:
  template<class S> friend istream&amp; operator>> ( istream&amp;, Node<S>&amp; );
  template<class S> friend ostream&amp; operator<< ( const ostream&amp;, const Node<S……



up++




********************************************************************************
*  C++经典之作下载链接: http://blog.csdn.net/jerryjbiao/article/details/7358796 *
********************************************************************************

#3


友元函数要先在类模板Node前面声明,在声明友元函数之前,还要先进行类模板Node的声明,
friend ostream& operator<< ( const ostream&, const Node& );这一条语句的第二个函数参数Node是类模板,不是类,改为:const Node<T> &
Node* next; 这一条语句也有错,Node是类模板,不是类,改为:Node<T> *next;

你的头文件中的代码修改如下:

#ifndef Node_H
#define Node_H

#include <iostream>
using std::istream;
using std::ostream;

template<Typename T>
class Node;

template<Typename T>
istream &operator >>(istream &,Node<T> &);

template<Typename T>
ostream &operator <<(ostream &,const Node<T> &);

template<Typename T>
class Node
{
 public:
 Node( int =0 );
    Node( const Node& );
    ~Node();
friend istream &operator >> <>(istream &,Node<T> &);
friend ostream &operator << <>(ostream &,const Node<T> &);

protected:
    Node<T> *next;
    T number;
};


下面是友元函数的定义:


template<Typename T>
istream &oprator >> <>(istream &input, Node<T> &temp)
{
Node *p = temp.next;
    for( cin>>temp.number; p!=NULL; p=p->next )
        cin >> p->number;
    return input;
}

ostream &operator << <>(ostream &output,const Node<T> &temp)
{
Node *p = next; 
    for( cout << number; p!=NULL; p=p->next )
        cout << " -> " << number;
    return output;

}

#4


引用 1 楼 pengzhixi 的回复:
1.将友元函数的实现放到类里面去。
2.或者将声明改为:
  template<class S>  friend istream&amp; operator>> ( istream&amp;, Node<S>&amp; );
  template<class S> friend ostream&amp; operator<< ( const ostream&amp;, const Node……


额,,那个S代表我定义的类Node?,,我还试了就字母S,就是不行啊,,具体说按我原来的代码怎么改呢,,谢谢

#5


按我的改,可以运行的

#6


你还要实现类模板Node的构造函数,在main函数所在的源文件中实现,其代码如下:


template<typename T>
Node<T>::Node( int n = 0):number(n)
{}

#7


引用 5 楼 lou0378 的回复:
按我的改,可以运行的



额,,刚改完,,和你一模一样除了在第二个函数定义时,多个 template<typename T>外,,,但问题还是一样。。

如果去掉那句,,问题更多

#8


你把头文件的名字写出来:然后把头文件里的代码全部贴出来,
然后再把类模板的定义和友元函数的定义所在的文件名字写出来,把源文件的全部代码贴出来

再帮你改

#9


Node *p = temp.next;
    for( cin>>temp.number; p!=NULL; p=p->next )
        cin >> p->number;
你友元函数中的代码有问题,比如:Node *p = temp.next;都没为指针p分配空间,就使用了,按照我的改,模板格式是没错的

#10


引用 9 楼 lou0378 的回复:
Node *p = temp.next;
    for( cin>>temp.number; p!=NULL; p=p->next )
        cin >> p->number;
你友元函数中的代码有问题,比如:Node *p = temp.next;都没为指针p分配空间,就使用了,按照我的改,模板格式是没错的



好吧,,麻烦了



//typename_Node.h

#ifndef Node_H
#define Node_H

#include<iostream>
using namespace std;

using std::istream;
using std::ostream;

template<typename T>
class Node;

template<typename T>
istream &operator >>( istream &,Node<T> &);

template<typename T>
ostream &operator <<( ostream &,const Node<T> &);

template<typename T>
class Node
{
public:
Node( int =0 );
Node( const Node& );
~Node();
friend istream& operator>> ( istream&, Node<T>& );
friend ostream& operator<< ( ostream&, const Node<T>& );
protected:
Node<T> *next;
T number;
};

template<typename T>
Node<T>::Node(  int length )
{
if( length <= 0 )  
{
cout << "length wrong ! ";
exit(0);      
}
Node* p = next = NULL;
number = 0;
for( int i=1; i<length; i++ )
{
p = new Node;
p->number = 0;
p = p->next;
}
p = NULL;
}
template<typename T>
Node<T>::Node( const Node& mylist )
{
if( mylist.next == NULL )
{
next = '\0';
number = 0;
return ;
}
Node *p1, *p2;
number = mylist.number;
p1 = next;
p2 = mylist.next
while( p2!=NULL )
{
p1->number = p2->number;
p1 = p1->next;
p2 = p2->next;
}
}
template<typename T>
Node<T>::~Node()
{
number = 0;
if( next==NULL )
return;
for( Node* p = next; p !=NULL; p = next )
{
next = next->next;
delete p;
}
}
template<typename T>
istream &operator>> <>( istream &input, Node<T> &temp )
{
Node *p = temp.next;
for( cin>>temp.number; p!=NULL; p=p->next )
cin >> p->number;
return input;
}
template<typename T>
ostream &operator<< <>( ostream &output, const Node<T> &temp )
{
Node *p = next; 
for( cout << number; p!=NULL; p=p->next )
cout << " -> " << number;
return output;
}
#endif

#11


引用 9 楼 lou0378 的回复:
Node *p = temp.next;
    for( cin>>temp.number; p!=NULL; p=p->next )
        cin >> p->number;
你友元函数中的代码有问题,比如:Node *p = temp.next;都没为指针p分配空间,就使用了,按照我的改,模板格式是没错的


我构造函数里的int是要建立链表的长度,,不是里面的数number大小。

我还准备重载[]的,,可以像数组那样使用的,,不过我自己看书太模糊。。。谢啦

#12


上面是你用到的头文件,你的源文件的代码呢,也贴出来,不然的话,头文件的代码修改了,源文件的代码没改,没保持一致也会编译错误的

#13


按照下面的修改,编译是没问题的,也就是语法和格式是正确的,至于功能的实现,要把代码全部贴出来才能知道,不知你用的是什么编译器,我用的是VS2008的编译器。

头文件的代码修改如下:


//typename_Node.h

#ifndef Node_H
#define Node_H

#include <iostream>

using std::ostream;
using std::istream;
using std::cin;
using std::cout;

template<typename T>
class Node;

template<typename T>
istream &operator >>( istream &,Node<T> &);

template<typename T>
ostream &operator <<( ostream &,const Node<T> &);

template<typename T>
class Node
{
public:
    Node( int =0 );
    Node( const Node<T>& );
    ~Node();
    friend istream& operator>> <>( istream&, Node<T>& );
    friend ostream& operator<< <>( ostream&, const Node<T>& );
protected:
    Node<T> *next;
    T number;
};

template<typename T>
Node<T>::Node(  int length = 0 )
{
    if( length <= 0 )  
    {
        cout << "length wrong ! ";
        exit(0);      
    }
    Node* p = next = NULL;
    number = 0;
    for( int i=1; i<length; i++ )
    {
        p = new Node;
        p->number = 0;
        p = p->next;
    }
    p = NULL;
}
template<typename T>
Node<T>::Node( const Node<T>& mylist )
{
    if( mylist.next == NULL )
    {
        next = '\0';
        number = 0;
        return ;
    }
    Node *p1, *p2;
    number = mylist.number;
    p1 = next;
    p2 = mylist.next
    while( p2!=NULL )
    {
        p1->number = p2->number;
        p1 = p1->next;
        p2 = p2->next;
    }
}
template<typename T>
Node<T>::~Node()
{
    number = 0;
    if( next==NULL )
        return;
    for( Node* p = next; p !=NULL; p = next )
    {
        next = next->next;
        delete p;
    }
}
template<typename T>
istream &operator>> <>( istream &input, Node<T> &temp )
{
    Node *p = temp.next;
    for( cin>>temp.number; p!=NULL; p=p->next )
        cin >> p->number;
    return input;
}
template<typename T>
ostream &operator<< <>( ostream &output, const Node<T> &temp )
{
    Node *p = next; 
    for( cout << number; p!=NULL; p=p->next )
        cout << " -> " << number;
    return output;
}

#endif

#14


引用 13 楼 lou0378 的回复:
按照下面的修改,编译是没问题的,也就是语法和格式是正确的,至于功能的实现,要把代码全部贴出来才能知道,不知你用的是什么编译器,我用的是VS2008的编译器。

头文件的代码修改如下:

C/C++ code

//typename_Node.h

#ifndef Node_H
#define Node_H

#include <iostream>

using std::ostream……



感谢啊,,我把一些其他毛病改过后,,差不多了,,但是析构有点问题。。不明白,,感觉很对啊。。

帮忙看下啊


template<typename T>
Node<T>::~Node()
{
number = 0;
for( Node* p = next; p !=NULL; p = next )
{
next = next->next;
delete[] p;
}
}



可以输入输出,,但是最后会有问题。。改为delete p;也不行

如果没有析构,,让计算机析构就没有问题了

我的cpp

//main.cpp
#include<iostream>
#include<ctime>
using namespace std;
#include"myList.h"

int main()
{
Node<int> a(5);
cin >> a;
cout << a;
}

其中#include<ctime>是为以后功能准备的,,可以忽视

再次感谢啊

#15


你想实现的功能是不是建立一个单链表啊?但你的构造函数有问题的,看下面的这个循环;
 for( int i=0; i<length; i++ )
    {
        p = new Node;
        p->number = i;
        p = p->next;
    }
第一个循环是,你的传递的参数length是5,可以执行,但当第二次循环时,执行到P =new Node是,又会调用构造函数,而且使用的默认值,此时length = 0;就会执行exit(0);推出循环,你需要修改构造函数和析构函数

#16


不知道到底你的程序想实现什么功能?说具体点,你想干什么

#17


引用 16 楼 lou0378 的回复:
不知道到底你的程序想实现什么功能?说具体点,你想干什么


嗯,,就是有这个问题呢。。

我就是想建立一个单链表,,然后会加上其他功能。。

好吧,,已经都麻烦你了,,剩下的我自己搞定吧。。对于类模板中重载输入输出,我已经查到一些资料了。。

太感谢了