【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:安全,量大,不缓存)( ...
随机推荐
- github上如何合并别人的pull request
https://github.com/Epix37/Hearthstone-Deck-Tracker/issues/1391 I fetch the code from your repository ...
- Hibernate映射之实体映射<转载>
实体类与数据库之间存在某种映射关系,Hibernate依据这种映射关系完成数据的存取,因此映射关系的配置在Hibernate中是最关键的.Hibernate支持xml配置文件与@注解配置两种方式.xm ...
- Spring-Data-JPA学习
Spring-Data-JPA结构图 网址: http://blog.sina.com.cn/s/blog_667ac0360102ecsf.html
- PHP Fileinfo组件越界内存破坏漏洞
漏洞版本: PHP PHP 5.x 漏洞描述: BUGTRAQ ID: 66002 CVE(CAN) ID: CVE-2014-2270 PHP是一种HTML内嵌式的语言. PHP的file程序在解析 ...
- textview的上下滑动效果
1.xml文件中 <TextView … android:scrollbars="vertical" ../> 2.java文件中 textview.se ...
- OS.ENVIRON()详解
OS.ENVIRON()详解
- 在 ASP.NET MVC4 中使用 NInject
Ninject是一个快如闪电.超轻量级的基于.Net平台的依赖注入框架.它能够帮助你把应用程序分离成一个个松耦合.高内聚的模块,然后用一种灵活的方式组装起来.通过使用Ninject配套你的软件架构,那 ...
- java 垃圾回收(堆内存)、以及栈内存的释放
一.Java的垃圾回收机制———解疑 Java的垃圾回收机制是Java虚拟机提供的能力,用于在空闲时间以不定时的方式动态回收无任何引用的对象占据的内存空间. 需要注意的是:垃圾回收回收的是无任何引用的 ...
- How to Convert a Date Time to “X minutes ago” in C# z
http://www.codeproject.com/Articles/770323/How-to-Convert-a-Date-Time-to-X-minutes-ago-in-Csh In one ...
- 在FOR中使用close window,循环次数大于1就会报异常
在FOR循环中执行以下动作: 场景:1.打开页面A, 2.点击A中的链接打开新的window, 3.将driver切换到新window, 4.close window 5.再切换到页面A 时出异 ...