若所有的参数皆需要类型转换——请为此采用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. Python3基础 __getattr__ 访问不存在的属性时,新增提示功能

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  2. Python3基础 str format 四舍六入五凑偶 保留一位小数

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  3. 啤酒和饮料|2014年蓝桥杯B组题解析第一题-fishers

    啤酒和饮料|2014年第五届蓝桥杯B组题解析第一题-fishers 啤酒和饮料 啤酒每罐2.3元,饮料每罐1.9元.小明买了若干啤酒和饮料,一共花了82.3元. 我们还知道他买的啤酒比饮料的数量少,请 ...

  4. [Shiro] - Shiro之进阶

    上一个知识点ssm, 哪里需要权限,哪里写注解@RequirePermission就行. 但是,真正项目开发的时候, 这种方式就很有局限性了, 当权限配置关系发生变化, 每次都要修改代码, 编译打包重 ...

  5. UVa 11584 划分成回文串

    https://vjudge.net/problem/UVA-11584 题意: 给出一串字符,把它划分成尽量少的回文串. 思路: 用d[i]表示划分到i时所能划分的最小个数,转移方程为d[i]=mi ...

  6. Java中的this

    首先this作为关键字其实是随着对象的创建而产生的,当我们调用对象的一个方法的时候: 例如: A a = new A(); a.f(1)  其实我们可以理解为a.f(a,1) 编译器默默的把所操作的对 ...

  7. Intel微处理器学习笔记(二) 三种模式

    三种模式:实模式.保护模式和平展模式. 实模式存储器(DOS存储器)位于00000H~FFFFFH,共1M空间(任何型号微处理器都支持). 保护模式存储器(Windows存储器)可位于整个保护存储系统 ...

  8. matplotlib-绘制精美的图表

    matplotlib库链接:http://matplotlib.org/gallery.html matplotlib绘制精美图标链接:http://old.sebug.net/paper/books ...

  9. VcCallC#_02

    1.VC代码:(vs2013运行正常) // ConsoleApplication_CallCS.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h&quo ...

  10. 微信小程序 - 简述

    1.小程序理解 基于微信的 免安装 MVVM 应用 编码使用 ES 6 一个页面基本组成:wxml wxss js ( html.css.js ) 2. 常见用法 ( 基本就是跟着例子走.. ) 设置 ...