C++中模板类使用友元模板函…

本文详细介绍了在C++中如何为模板类定义友元函数,并提供了三种友元声明方式的具体示例,包括普通非模板类或函数的友元声明、类模板或函数模板的友元声明以及特定实例的友元声明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题始于学习数据结构,自己编写一个单链表,其中用到了重载输出运算符<<,我写的大约这样:

template <class T> class List{
    friend std::ostream& operator << (std::ostream& os,const List<T>& slist);
    //……
};用vs2008可编译,但无法链接:无法解析的外部符号……

后来上网查改为template <class T> class List{
    friend std::ostream& operator <<  <>(std::ostream& os,const List<T>& slist);
    //……
};

就可以了。不知所以然,查了下《C++ Primer》才弄明白。

好了,进入正题:

在类模板中可以出现三种友元声明:
(1)普通非模板类或函数的友元声明,将友元关系授予明确指定的类或函数。
(2)类模板或函数模板的友元声明,授予对友元所有实例的访问权。
(3)只授予对类模板或函数模板的特定实例的访问权的友元声明。

要注意的是,友元函数并非成员函数,是改变了它对类成员的访问权限。

(1)没有什么好说的,如:

template<class T>

class A{

   friend void fun();

//...

};
此例中fun可访问A任意类实例中的私有和保护成员

(2)

template<class T>

class A{

  template<class T>

   friend void fun(T u);

//...

};

这时友元使用与类不同的模板形参,T可以是任意合法标志符,友元函数可以访问A类的任何类实例的数据,即不论A的形参是int,double或其他都可以。

(3)

template<class T>

class A{

   friend void fun<T>(T u);

//...

};

此时fun只有访问类中特定实例的数据。换句话说,此时具有相同模板实参的fun函数与A类才是友元关系。即假如调用fun时其模板实参为int,则它只具有A<int>的访问权限。当然friend void fun<T>(T u);中<>中的T可以是任意类型,比如int,double等

回到原问题,按(3)可改为:
template <class T> class List{
    friend std::ostream& operator << <T>(std::ostream& os,const List<T>& slist);
    //……
};

按(2)可改为:

template <class T> class List{

    template <class T>
    friend std::ostream& operator << (std::ostream& os,const List<T>& slist);
    //……
};
在这里其实两者实现的最终效果一样的,因为调用输出运算符时需要访问的类实例的对象是它本身,所以形参T在第一种改法中一定匹配。


  

 

对类建立友元函数很容易。但是迁移到模板上却容易出现让人摸不着头脑的连接错误。
层次不够,不做分析,单纯介绍两种为类模板定义友元函数的方法

  1 封闭型

[转载]C++中模板类使用友元模板函数 template <  typename  >
[转载]C++中模板类使用友元模板函数
class  MyClass
[转载]C++中模板类使用友元模板函数[转载]C++中模板类使用友元模板函数
[转载]C++中模板类使用友元模板函数 {
[转载]C++中模板类使用友元模板函数    friend 
void function( MyClass< > &arg )
[转载]C++中模板类使用友元模板函数[转载]C++中模板类使用友元模板函数    
[转载]C++中模板类使用友元模板函数{
[转载]C++中模板类使用友元模板函数        [转载]C++中模板类使用友元模板函数
[转载]C++中模板类使用友元模板函数     }

[转载]C++中模板类使用友元模板函数 }
;
  要点:友元函数定义在模板体内。

              2 开放型
[转载]C++中模板类使用友元模板函数 template <  typename  >
[转载]C++中模板类使用友元模板函数
class  MyClass
[转载]C++中模板类使用友元模板函数[转载]C++中模板类使用友元模板函数
[转载]C++中模板类使用友元模板函数 {
[转载]C++中模板类使用友元模板函数    template
< typename >
[转载]C++中模板类使用友元模板函数    friend 
void function( MyClass< > &arg );
[转载]C++中模板类使用友元模板函数 }
;
[转载]C++中模板类使用友元模板函数
[转载]C++中模板类使用友元模板函数template
<  typename  >
[转载]C++中模板类使用友元模板函数
void  function( MyClass <   >   & arg )
[转载]C++中模板类使用友元模板函数[转载]C++中模板类使用友元模板函数
[转载]C++中模板类使用友元模板函数 {
[转载]C++中模板类使用友元模板函数    [转载]C++中模板类使用友元模板函数
[转载]C++中模板类使用友元模板函数 }
  要点:模板体内要另建模板。 
  
  3 告诉编译器声明的设个是模板
[转载]C++中模板类使用友元模板函数 #include  < iostream >
[转载]C++中模板类使用友元模板函数
using   namespace  std;
[转载]C++中模板类使用友元模板函数
[转载]C++中模板类使用友元模板函数template 
<  typename  >
[转载]C++中模板类使用友元模板函数
class  A
[转载]C++中模板类使用友元模板函数[转载]C++中模板类使用友元模板函数
[转载]C++中模板类使用友元模板函数 {
[转载]C++中模板类使用友元模板函数    friend ostream 
&operator<< < >ostream &const A< > & );
[转载]C++中模板类使用友元模板函数 }
;
[转载]C++中模板类使用友元模板函数
[转载]C++中模板类使用友元模板函数template 
<  typename  >
[转载]C++中模板类使用友元模板函数ostream 
& operator <<  ostream  & output,  const  A <   >   & )
[转载]C++中模板类使用友元模板函数[转载]C++中模板类使用友元模板函数
[转载]C++中模板类使用友元模板函数 {
[转载]C++中模板类使用友元模板函数    output 
<< "重载成功" << endl;
[转载]C++中模板类使用友元模板函数    
return output;
[转载]C++中模板类使用友元模板函数 }

[转载]C++中模板类使用友元模板函数
[转载]C++中模板类使用友元模板函数
int  main()
[转载]C++中模板类使用友元模板函数[转载]C++中模板类使用友元模板函数
[转载]C++中模板类使用友元模板函数 {
[转载]C++中模板类使用友元模板函数    A
< int > a;
[转载]C++中模板类使用友元模板函数    cout 
<< a;
[转载]C++中模板类使用友元模板函数 }
要点:显示地在重载的运算符或者函数后面加上模板声明< T >,告诉编译器友元函数是一个类型一致的模板。

  建议:
                        如果希望使用函数与模板特化的类型相对应,则使用方法3(模板显示声明)
                        如果希望使用函数与模板特化的类型相独立,则使用方法2(二重模板)
                        简短的内联函数使用方法1
 
本文来自优快云博客,转载请标明出处: http://blog.youkuaiyun.com/squarereal/archive/2009/09/23/4579950.aspx
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值