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

经常使用C++的程序猿(希望更多的程序媛),一般不会同意让classes支持类型转换,至于为什么,请看后续的博客。假如我们设计一个表示有理数的class,允许”整数隐式转换为有理数似乎很合理“。首先来一个简单的实现。

class Rational
{
public:
Rational(int numerator = 0,int denominator = 1; //允许int-to-Rational隐式转换
int numerator()const;
int denominator()const;
const Rational operator*(const Rational& rhs)const; //有理数的乘法
...
};

有理数,我们很自然地为他实现了乘法的运算。我们可以轻松地实现两个有理数相乘,但是,假如我们想要进行混合运算呢?在下面的例子中,2在第一个参数与第二个参数的位置进行隐私类型转换。


Rational half(1,2);
half = half * 2; //1. 通过编译
half = 2 *half; //2. 无法通过编译

为什么会这样呢?对于1,编译器解释如下,所以很正常地通过了编译。

operator*(Rational& this,Rational& rhs);    //函数的定义部分
//第一个参数是没办法改变的,一定是被乘数
half.operator(Rational(2)); //函数的调用部分,2被隐式转换为了有理数
//与下面的代码一致
const Rational temp(2);
result = half * temp;

编译器拿到2的时候,知道operator*()需要一个Rational,也知道只要调用Rational的构造函数就能够变出一个适当的Rational,所以,它就做了。

结果就是上面的例子。当然,必须存在non-explicit编译器才会这么做。

而对于2中的代码呢,编译器首先试着如下解释

2.operator*(half);

很明显,2.operator()是不存在的东西,所以,编译器会尝试着寻找一个non-memb operator(),但结果是:没有找到。所以只能返回一个错误。

很明显,上面对于同一个操作符,却有了两种截然不同的结果,你十分抵触。然后你就会义愤填膺地把构造函数修改为explicit。结果是:两者一致了,都不支持混合运算。但是,我们的目标不仅仅在于一致性,我们还希望它支持混合运算。那么,请拿出我们的利器:non-member函数。我们暂时允许编译器执行隐式类型转换。

class Rational
{
...
};
const Rational operator*(const Rational& lhs,const Rational& rhs);
Rational half(1,2);
half = half * 2; //通过编译
half = 2 * half; //通过编译

真的是峰回路转疑无路,千辛万苦终于找到可行之道。对于上面的代码,编译器会对每个2都转换为Rational(2)。当你完成了一天的工作后,最后一个要操心的问题是:是否需要一个non-member friend函数?假如否定的,member的对立面不是non-member friend函数。使用了friend,意味着公开自己的所有隐私。这种严重破坏自身隐私的可不是好事,可以参考以下的博客太过亲密往往不好——用NON-MEMBER,NON-FRIEND替换MEMBER函数还有为了更好更方便地活着——爱上PRIVATE.

总结一下

  1. 假如你需要为某个函数的所有参数都进行类型转化的时候,这个函数必须是non-member。

  2. member的对立面不是non-member friend,请慎用friend。

若所有的参数皆需要类型转换——请为此采用non-member函数的更多相关文章

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

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

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

    NOTE: 1.如果你需要为某个函数的所有参数(包括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. 【24】若所有参数皆需类型转换,请为此采用non-members函数

    1.令class支持隐式类型转换,往往是个糟糕的主意.但有些情况是合理的,比如数值类型.考虑,有理数Rational有分子,分母两个字段,缺省参数值为0,1.Ration a = 2;我们期望构造一个 ...

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

  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. 第一个html文件

    1.新建记事本文件,后缀改为.html 2.添加: <html>  <head>  <title>jude`s first web</title>  & ...

  2. return false break;

    js中的return false;  break; , , , , ]; var list2 = ['a', 'b', 'c', 'd']; ; j < list2.length; j++) { ...

  3. 【eclipse】聚合工程maven启动Tomcat报错

    严重: Error configuring application listener of class严重: Skipped installing application listeners due ...

  4. UVa 1603 破坏正方形

    https://vjudge.net/problem/UVA-1603 题意:有一个火柴棍组成的正方形网格,计算至少要拿走多少根火柴才能破坏所有正方形. 思路:从边长为1的正方形开始遍历,将正方形的边 ...

  5. 实现简单的ORM

    介绍 本篇将介绍实现简单的ORM,即:对数据表的通用操作:增.删.改.查 数据访问层 数据访问层类图 类说明: 1.DbProvider(供应):为数据操作提供基本对象,如:连接.操作对象.事务... ...

  6. MVC ---- T4模板的小练习

    1.先建立两个模板文件 :Manger.ttinclude.DBHelper.ttinclude Manger.ttinclude <#@ assembly name="System. ...

  7. Java 面向对象之static,final,匿名对象,内部类,包,修饰符

    01final关键字概念 A: 概述 继承的出现提高了代码的复用性,并方便开发.但随之也有问题,有些类在描述完之后,不想被继承, 或者有些类中的部分方法功能是固定的,不想让子类重写.可是当子类继承了这 ...

  8. NPOI操作

    1.操作Excel 准备生成的公共方法(将数据源DataTable转换成MemoryStream) /// <summary> /// 生成Excel /// </summary&g ...

  9. js 文件上传

    <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8&quo ...

  10. NeteaseCloudWebApp模仿网易云音乐的vue自己从开源代码中学习到的

    github地址: https://github.com/javaSwing/NeteaseCloudWebApp 1.Vue.prototype.$http = Axios // 类似于vue-re ...