关于函数模板在类模板中声明为友元的一些心得

用类模板设计时,有时需要在类定义中声明友元函数,比如重载输出操作符<<,而当友元函数是模板函数时,则需要满足一些声明和定义的规则。

如,当我编写一个顺序表类模板时,加入了重载<<的友元模板如下:

template <typename T> class SeqList{
    friend std::ostream& operator << (std::ostream& os,const SeqList<T>& slist);
    //……
};

此时在main.cpp文件中定义operator << 如下
template <typename T>
ostream& operator << (ostream& os,const SeqList<T>& slist){
    return  slist.printList(os);
}

编译通过,但链接报错!error LNK2019: 无法解析的外部符号 ……

由于我水平有限,至今仍不能读懂链接错误,唯有求助网络及红宝书(C++ Primer)了。


以下来自C++ Primer:
在类模板中可以出现三种友元声明……
(1)普通非模板类或函数的友元声明,将友元关系授予明确指定的类或函数。
(2)类模板或函数模板的友元声明,授予对友元所有实例的访问权。
(3)只授予对类模板或函数模板的特定实例的访问权的友元声明。
……
想要限制对特定实例化的友元关系时,必须在可以用友元声明之前声明类或函数
……

读完后我的理解是
当声明的友元函数不是模板函数,或者该函数是与类模板有不一样的typename的函数模板时,在类中声明该函数友元相当于声明了该函数。

但显然,上述遇到的问题属于第(3)种,而按书中所说,在声明友元std::ostream& operator <<时,应当先在类SeqList<T>定义之前声明该函数(而这又意味着在声明该函数前还需先声明类SeqList——template <typename T> class SeqList;)

在CSDN论坛中又搜到另一种方法。


上述问题的解决办法可总结如下两种:
1、声明友元前先声明函数模板,原方案变为
template <typename T> class SeqList;//声明类

template <typename T>           //声明重载函数模板
std::ostream& operator << (std::ostream&,const SeqList<T>&);

template <typename T> class SeqList{
    //声明为友元

    friend std::ostream& operator << <T>(std::ostream& os,const SeqList<T>& slist);
    //……   
}
//定义函数模板时不变
template <typename T>
ostream& operator << (ostream& os,const SeqList<T>& slist){
    return  slist.printList(os);
}

2、无需在类定义前声明函数模板,而是将友元函数的定义直接写在类的定义中
template <typename T> class SeqList{
    //……

    //直接定义函数       
    friend std::ostream& operator << <T>(std::ostream& os,const SeqList<T>& slist){
        return  slist.printList(os);
    }
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值