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函数的更多相关文章

  1. 若所有的参数皆需要类型转换——请为此采用non-member函数

    若所有的参数皆需要类型转换--请为此采用non-member函数 经常使用C++的程序猿(希望更多的程序媛),一般不会同意让classes支持类型转换,至于为什么,请看后续的博客.假如我们设计一个表示 ...

  2. Effective C++ -----条款24:若所有参数皆需类型转换,请为此采用non-member函数

    如果你需要为某个函数的所有参数(包括被this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member.

  3. [Effective C++ --024]若所有参数皆需类型转换,请为此采用non-member函数

    引言 假设我们有这样的类: class A{ public: A(, ) {}; int num() const; int den() const; const A operator* (const ...

  4. [EffectiveC++]item24:若所有参数皆需类型转换,请为此采用non-member函数

    Declare non-member functions when type conversions should apply to all parameters. 104页 只有当参数被列于参数列( ...

  5. 读书笔记_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); } ...

  6. 条款24:若所有参数皆需要类型转换,请为此采用non-member函数(Declare non-member functions when type conversions should apply to all parameters)

    NOTE: 1.如果你需要为某个函数的所有参数(包括this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member.

  7. 条款24:如果所有的参数都需要类型转换,那么请为此采用non-member函数

    首先还是下面这个class; class Rational{ public: Rational(, ); int numurator() const; int denominator() const; ...

  8. 微信h5支付出现“商家参数格式有误,请联系商家解决”

    在浏览器进行微信h5支付时出现:

  9. js中ajax连接服务器open函数的另外两个默认参数get请求和默认异步(open的post方式send函数带参数)(post请求和get请求区别:get:快、简单 post:安全,量大,不缓存)(服务器同步和异步区别:同步:等待服务器响应当中浏览器不能做别的事情)(ajax和jquery一起用的)

    js中ajax连接服务器open函数的另外两个默认参数get请求和默认异步(open的post方式send函数带参数)(post请求和get请求区别:get:快.简单 post:安全,量大,不缓存)( ...

随机推荐

  1. Oracle数据导入导出imp/exp sp2-0734:未知的命令开头'imp...解决方法

    Oracle数据导入导出imp/exp sp2-0734:未知的命令开头'imp...解决方法   sp2-0734:未知的命令开头'imp 忽略了剩余行默认分类   www.2cto.com  应该 ...

  2. 抱怨IT公司人才缺乏?留住现有人才方是正途

    摘要:员工的好坏决定着IT公司的未来,可很多IT公司在抱怨之时自己的人才却正在流失,如何留住现有的优秀员工?国外知名经理人Sharon Florentine建议:改善自己的管理.让员工不断地学习.创建 ...

  3. POJ3921

    搜索 每次找出最短路 如果小于等于k 那么必定这里有一点是要被删掉的 枚举这个最短路径上的每一个点 (一般不会超过20) 将其相邻边删除 用dijskra求最短路径并且保存即可 深度搜索 #inclu ...

  4. 逆序对的相关问题:bzoj1831,bzoj2431

    先从简单一点的bzoj2431入手: n个数1~n已经限定了,所以 对于1~i-1,新加入i,最多可以增加i-1个逆序对,最少增加0个逆序对 f[i,j]表示1~i形成的序列逆序对为j的方案数 比较容 ...

  5. TRSWCM学习问题总结

    1,置标属性"id"是用来制定调用那个栏目的数据(全字配备,可以文字匹配好奇怪,好不专业.所以建议创建栏目或者站点的时候,将唯一标识设置成英文,这样才符合程序比对习惯) 2,需要添 ...

  6. LeetCode Summary Ranges (统计有序数列范围)

    题意:给出个有序不重复数列(可能负数),用缩写法记录这个数列. 思路:找每个范围的起始和结束即可. class Solution { public: vector<string> summ ...

  7. 如何升级cordova插件

    cordova-plugin-code-push插件在cordova6.1.1 ios环境中出现异常. 所以尝试升级cordova-plugin-code-push来解决这个问题. 升级没有被依赖的插 ...

  8. POJ 3208-Apocalypse Someday(数位dp)

    题意:给定n,输出第n大包含666的数字. 分析:dp[i][j][k][l]表示 长度为i,当前位是否是6,前一位是否6,是否已经包含666,表示的数量,再用二分找出第n大的这样的数字. #incl ...

  9. Selenium2Library系列 keywords 之 _SelectElementKeywords 之_get_select_list_options(self, select_list_or_locator)

    def _get_select_list_options(self, select_list_or_locator): if isinstance(select_list_or_locator, Se ...

  10. activemq 异步和同步接收

    来点实在的代码,用例子来说明: 1.异步接收,主要设置messageListener.,然后编写onmessage方法,很简单 a.客户端发送5条消息 package ch02.chat; impor ...