方法一
#include<iostream>
using namespace std;
template <class T>
class Test
{
private:
T num;
public:
Test( T n)
{
num=n;
}
friend ostream& operator<< <>(ostream &out,const Test<T> &);
};
template <class T>
ostream& operator<< <>(ostream &out,const Test<T> &obj)
{
out<<obj.num;
return out;
};
void main()
{
Test<int> t(414);
cout<<t;
}
方法二
// 第二种格式
#include <iostream>
using namespace std;
template<class T>
class Test
{
public:
template<class S> // 注意<class S>S
friend ostream& operator << (ostream& out, const Test<S>& obj);
Test(T n = 0) :num(n) {}
Test(const Test<T>& copy)
{
num = copy.num;
}
private:
T num;
};
// 注意<class T>和<class S>都行
template<class T>
ostream& operator << (ostream& out, const Test<T>& obj)
{
out << obj.num << endl;
return out;
}
int main(){
Test<int> t(2);
cout << t;
return 0;
}
正确的写法就是代码段中的写法。<>也必不可少,其实<>有两
重意思:
一是,表明此友元函数是函数模板;
二是,此模板使用的模板类型参数为当前
模板类的类型参数class。
关于friend关键字:
· 虚函数必须是成员函数。如果f必须是虚函数,就让它成为c的成员函数。
operator>>;和operator<<;决不能是成员函数。如果f是operator>>;或operator<<;
,让f成为非成员函数。如果f还需要访问c的非公有成员,让f成为c的友元函数。
·只有非成员函数对最左边的参数进行类型转换。如果f需要对最左边的参数进行类型转换,让f成为非成员函数。如果f还需要访问c的非公有成员,让f成为c的友元函数。
·其它情况下都声明为成员函数。如果以上情况都不是,让f成为c的成员函数。
然后在类体外对友元函数进行定义,定义的格式和普通函数相同,但可以通过对象作为参数直接访问对象的私有成员。
1)必须在类的说明中说明友元函数,说明时以关键字friend开头,后跟友元函数的函数原型,友元函数的说明可以出现在类的任何地方,包括在private和public部分;
2)注意友元函数不是类的成员函数,所以友元函数的实现和普通函数一样,在实现时不用"::"指示属于哪个类,只有成员函数才使用"::"作用域符号;
3)友元函数不能直接访问类的成员,只能访问对象成员,
4)友元函数可以访问对象的私有成员,但普通函数不行;
5)调用友元函数时,在实际参数中需要指出要访问的对象,
6)类与类之间的友元关系不能继承。