看看下面这个例子:

 1 template<typename T>
 2 class Rational{
 3 public:
 4     Rational(const T & numerator, const T & denominator);
 5     const T numerator()const;
 6     const T denominator() const;
 7 };
 8 template<typename T>
 9 const Rational<T> operator*(const Rational<T>& lhs,
10                             const Rational<T>& rhs);
11 Rational<int> oneHalf(1,2);
12 Rational<int> result = oneHalf*2;

上面的最后一个式子看起来好像能够通过编译,但是实际上不能,因为模版的关系,编译器不会知道我们想调用的是哪个函数。
上面式子能推倒出来,正确的可能就是编译器使用Rational<int>的non-explicit构造函数将2转换,但是编译器进行实参推倒的时候不会将隐式转换放到考虑的范围里面。
而解决上述问题的有效方法就是,不要让operator*需要去进行参数的推倒,而是将其设为Rational的一个friend函数:
 1 template<typename T>
 2 class Rational{
 3 public:
 4     Rational(const T & numerator, const T & denominator);
 5     const T numerator()const;
 6     const T denominator() const;
 7     friend
 8     const Rational operator*(const Rational<T> & lhs,
 9                             const Rational<T> & rhs);
10 };

这样,当oneHalf声明出来的时候,就相当于自动声明出来了上面的operator*,这样的隐式转换同样也来能够成功。
在一个class template里面,template名称可以被用来当作“template何其参数的建议表达形式”,所以说上面的形式和下面的
1   friend
2     const Rational<T> operator*(const Rational<T> & lhs,
3                             const Rational<T> & rhs);

const Rational<T> & rhs);
实际上是相同的。

但实际上上面咋Rational外部去给operator*一个定义是行不通的,因为模板的原因,这个定义必须被放置在类的内部,就像下面这样:
 1 template<typename T>
 2 class Rational{
 3 public:
 4     Rational(const T & numerator, const T & denominator);
 5     const T numerator()const;
 6     const T denominator() const;
 7     friend
 8     const Rational<T> operator*(const Rational<T> & lhs,
 9                             const Rational<T> & rhs)
10     {
11         return Rational(lhs.numerator() * rhs.numerator(),
12                         lhs.denominator() * rhs.denominator());
13     }
14 };

这里的使用friend实际上有其独到的意义:为了让类型转换可以发生在所有的实参身上,需要一个non-member,为了让这个函数被自动具体化,我们需要将他们声明在class内部,而在class内部声明non-member函数的唯一方法就是将他声明称friend。!!
小结:当编写一个class template的时候,起所提供的“与此template相关的”函数支持“所含参数的隐式类型”时,应该将那些函数定义为“class template 内部的”friend函数

转载于:https://www.cnblogs.com/-wang-cheng/p/4889821.html

条款46:需要类型转换的时候请为模板定义非成员函数相关推荐

  1. 需要类型转换时请为模板定义非成员函数——条款46

    条款24讨论过为什么唯有non-member函数才有能力"在所有实参身上实施隐式类型转换",该条款并以Rational class的operator*函数为例.我强烈建议你继续看下 ...

  2. C++ - 模板函数须要类型转换时使用友元(friend)模板函数

    模板函数须要类型转换时使用友元(friend)模板函数 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24357301 非模板函数 ...

  3. 请用JavaScript实现一个函数,接受一-个IP白名单列表whitelist以及列表ipList

    请用JavaScript实现一个函数,接受一-个IP白名单列表whitelist以及 列表ipList,判断输入的ipList中是否有任何ip包含在whitelist中,如果存在返回true,如果都不 ...

  4. [react] 请描述你对纯函数的理解?

    [react] 请描述你对纯函数的理解? 给定了输入的参数,则函数抛出的数据就是确定的 函数内没有副作用(定时器,ajax等) 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很容易, 但坚持一 ...

  5. c语言给一个函数添加功能,【C语言】请编写实现以下功能函数:实现对一个8bit数据(unsigned char)的指定位(例如第8位)的置0或置1操作,并保持其他位不变...

    /*请编写实现以下功能函数:实现对一个8bit数据(unsigned char)的指定位(例如第8位)的置0或置1操作,并保持其他位不变. 函数原型:void bit_set(unsigned cha ...

  6. 矩阵转置算法 oracle,请编写程序fun,函数的功能是:实现B=A+Aˊ,即把矩阵A加上A的转置,存放在矩阵B中。计算结果在main函...

    请编写程序fun,函数的功能是:实现B=A+Aˊ,即把矩阵A加上A的转置,存放在矩阵B中.计算结果在main函 更多相关问题 假定砌块对孔砌筑,孔内不灌实混凝土,柱头全截面设一预制刚性垫块,且梁端有效 ...

  7. C++ 实验四 NO. 3 书店的前台收银销售类, 请完成该类定义,实验并且要满足: 1)向购物车中添加书籍;2):查看购物车;3):结算

    //************************************************************************************************** ...

  8. 区分一下强制类型转换运算符重载/赋值运算符重载/对象定义的赋值

    这三个名字可能很绕,看着也很不一样,但其实是三个很容易混淆的概念,并且经常在实际编程中遇到.这里拿出来比较一下. 首先是强制类型转换运算符的重载,作用是当前对象向其他类型的转换,常见的形式是 oper ...

  9. Python 中的特殊方法(定制类):__str__、__cmp__、__len__、数学运算、类型转换、@property运用、__slots__和__call__函数

    Python中的特殊方法 Python的特殊方法定义在 class中,不需要直接进行显示调用,Python的某些操作符或者函数会自动调用对应的特殊方法.这些方法如:__str__().__len__( ...

最新文章

  1. sql查询第二大的记录(转)
  2. android自定义水波纹,Android自定义View——实现水波纹效果类似剩余流量球(示例代码)...
  3. JetBrains PyCharm 2018.2.5 x64永久激活教程
  4. 在ASP.Net 2.0中实现多语言界面的方法
  5. mysql双主 绿色_mysql (双主,互主)
  6. RAC srvctl 命令报 libpthread.so.0 cannot open shared object file No such file or directory 解决方法...
  7. hive left join入门
  8. 【ABAP系列】SAP ABAP 从FTP服务器读取文件到本地
  9. [华为机试真题][2014]63.等式变换
  10. 信息系统项目管理师考试难?一次过备考经验分享给大家
  11. Hexo NexT主题自定义背景图片
  12. php5.3不能连接mssql数据库的解决方法
  13. 基于Spark实现电影点评系统用户行为分析—RDD篇(一)
  14. Linux学习 day05之用户组权限管理
  15. 最新版YOLOv6训练自己的数据集(超详细完整版!)
  16. Weex 初体验(1)
  17. 视频聊天室如何成功赚钱分享攻略一
  18. DP线和HDMI线相比哪个比较好用?
  19. 模拟模拟交易系统(三)——UI设计
  20. 九龙证券|A股苏州板块迎来“200+”里程碑

热门文章

  1. C++和C语言函数相互调用
  2. linux ethtool 查看网卡状态
  3. 关于非阻塞的recv的时候返回的处理
  4. 互联网寒冬!技术站最全MySQL数据库实战规范
  5. 连续四年百度Android岗必问面试题!Android校招面试指南
  6. linux eclipse设置颜色,Linux Eclipse美化:解决工具栏过大和 Javadoc背景色修改
  7. 文件在线预览 图片 PDF Excel Word
  8. python使用GUI(图形用户界面)
  9. 第五百一十八天 how can I 坚持
  10. mac 下终端 操作svn命令 以及出现证书错误的处理方法