【24】若所有参数皆需类型转换,请为此采用non-members函数
1、令class支持隐式类型转换,往往是个糟糕的主意。但有些情况是合理的,比如数值类型。考虑,有理数Rational有分子,分母两个字段,缺省参数值为0,1。Ration a = 2;我们期望构造一个分子为2,分母为1的有理数,这是非常合理和自然的。因此,Rational的构造方法为Ration(int numerator =0, int denominator =1);不添加explicit。
2、考虑Rational 有个成员方法 operator*,如下:
const Ration operator*(const Rational& rhs) const;
Rational a (1,2);
Rational result;
result = a*2; // OK
result = 2*a; // Error
为什么?
对于a*2,2会隐式转化为Rational,而对于2*a,2不会隐式转化为Rational。这种情况下,编译器尝试查找non-member方法的调用,即operator(2,a); 在当前名称空间或者全局global作用域查找不到,报错。
3、分析下,为什么对于2*a,2不会隐式转化为Rational。
调用方法的时候,如果没有完全匹配的方法,编译器尝试进行一次隐式类型转换,使之与方法匹配成功。可认为编译器做了一次适配的过程,实参与形参类型不一致,把实参转化为形参的类型,从而匹配成功。
对于a*2,2对应形参,而对于2*a,2对应this指针常量。不能隐式转化为this指针。再接着思考,为什么不能转化为this指针?
假如可以隐式转化为this指针,那么有成千上万的类(没有声明explicit构造方法),当调用2*a的时候,编译器必须遍历每一个类,查看这个类中是否有* Rational的成员方法,显然不可能。
4、另外,还有一点,隐式类型转换只能进行一次,不能进行多次。也就是说,2 -> XXX -> Person是不可行的。思考下,为什么?
假如隐式类型转换允许多次,就意味着,从2 到Person的转换过程,编译器必须查找出所有可能的转换路径,这显然不切实际。即使,找到了所有的转换路径,那么,存在多个转换路径,到底使用哪一个呢?
5、怎么解决上面的问题呢? 即2*a。
既然不能隐式转换为this指针,那么就是用non-member方法。这样的话,无论对于哪个形参需要隐式类型转化,都可以。编译器从当前名称空间或者全局作用域,查找operator*(Rational ,Rational),这种形式的方法毕竟很有限。
6、定义的non-member方法,是否需要声明为Rational的friend方法?
根据经验,尽量避免使用friend,为啥?因为friend破坏了封装。因此,如果不需要访问Rational的private成员,就不要声明为friend。
【24】若所有参数皆需类型转换,请为此采用non-members函数的更多相关文章
- 若所有的参数皆需要类型转换——请为此采用non-member函数
若所有的参数皆需要类型转换--请为此采用non-member函数 经常使用C++的程序猿(希望更多的程序媛),一般不会同意让classes支持类型转换,至于为什么,请看后续的博客.假如我们设计一个表示 ...
- Effective C++ -----条款24:若所有参数皆需类型转换,请为此采用non-member函数
如果你需要为某个函数的所有参数(包括被this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member.
- [Effective C++ --024]若所有参数皆需类型转换,请为此采用non-member函数
引言 假设我们有这样的类: class A{ public: A(, ) {}; int num() const; int den() const; const A operator* (const ...
- [EffectiveC++]item24:若所有参数皆需类型转换,请为此采用non-member函数
Declare non-member functions when type conversions should apply to all parameters. 104页 只有当参数被列于参数列( ...
- 读书笔记_Effective_C++_条款二十四: 若所有参数皆需类型转换,请为此采用non-member函数
class A { private: int a; public: A(int x) :a(x){} A operator*(const A& x) { return A(a*x.a); } ...
- 条款24:若所有参数皆需要类型转换,请为此采用non-member函数(Declare non-member functions when type conversions should apply to all parameters)
NOTE: 1.如果你需要为某个函数的所有参数(包括this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member.
- 条款24:如果所有的参数都需要类型转换,那么请为此采用non-member函数
首先还是下面这个class; class Rational{ public: Rational(, ); int numurator() const; int denominator() const; ...
- 微信h5支付出现“商家参数格式有误,请联系商家解决”
在浏览器进行微信h5支付时出现:
- js中ajax连接服务器open函数的另外两个默认参数get请求和默认异步(open的post方式send函数带参数)(post请求和get请求区别:get:快、简单 post:安全,量大,不缓存)(服务器同步和异步区别:同步:等待服务器响应当中浏览器不能做别的事情)(ajax和jquery一起用的)
js中ajax连接服务器open函数的另外两个默认参数get请求和默认异步(open的post方式send函数带参数)(post请求和get请求区别:get:快.简单 post:安全,量大,不缓存)( ...
随机推荐
- 1022. Genealogical Tree(topo)
1022 简单拓扑 不能直接dfs 可能有不联通的 #include <iostream> #include<cstdio> #include<cstring> # ...
- 1701. Ostap and Partners(并查集-关系)
1701 又是类似食物链的这一类题 这题是找与根节点的和差关系 因为0节点是已知的 为0 那么所有的都可以转换为与0的和差关系 可以规定合并的两节点 由大的指向小的 然后再更新和差关系 有可能最后有 ...
- Css3 Media Queries移动页面的样式和图片的适配问题(转)
CSS3 Media Queries 摘自:http://www.w3cplus.com/content/css3-media-queries Media Queries直译过来就是“媒体查询”,在我 ...
- C#字符串与char数组互转!
字符串转换成Char数组string str="abcdefghijklmnopqretuvwxyz";char[] chars=str.ToCharArray(); char数组 ...
- python20151130
tab和空格混排是报错的 import os #如何获取当前路径 #当前路径可以用'.'表示,再用os.path.abspath()将其转换为绝对路径 print(os.path.abspath('. ...
- 【转】android 最新 NDK r8 在window下开发环境搭建 安装配置与使用 详细图文讲解,完整实际配置过程记录(原创)
原文网址:http://www.cnblogs.com/zdz8207/archive/2012/11/27/android-ndk-install.html android 最新 NDK r8 在w ...
- HTML入门基础教程相关知识
HTML入门基础教程 html是什么,什么是html通俗解答: html是hypertext markup language的缩写,即超文本标记语言.html是用于创建可从一个平台移植到另一平台的超文 ...
- Android开发:如何实现TCP和UDP传输
TCP和UDP在网络传输中非常重要,在Android开发中同样重要. 首先来看一下什么是TCP和UDP. 什么是TCP? TCP:Transmission Control Protocol 传输控制协 ...
- Month Calendar
http://www.codeproject.com/Articles/10840/Another-Month-Calendar#xx4614180xx Another Month Calendar ...
- 劳动节BT5 aircrack-ng战记
劳动节最后一天没事,想捣鼓一下BT5破解无线wep/wpa,BT5+virtual box早已准备就绪,上网专门找了一些资料,并买了一个据评测很兼容的usb网卡tp-link wn722n,芯片代号A ...