若所有的参数皆需要类型转换——请为此采用non-member函数
若所有的参数皆需要类型转换——请为此采用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.
总结一下
假如你需要为某个函数的所有参数都进行类型转化的时候,这个函数必须是non-member。
member的对立面不是non-member friend,请慎用friend。
若所有的参数皆需要类型转换——请为此采用non-member函数的更多相关文章
- Effective C++ -----条款24:若所有参数皆需类型转换,请为此采用non-member函数
如果你需要为某个函数的所有参数(包括被this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member.
- 条款24:若所有参数皆需要类型转换,请为此采用non-member函数(Declare non-member functions when type conversions should apply to all parameters)
NOTE: 1.如果你需要为某个函数的所有参数(包括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页 只有当参数被列于参数列( ...
- 【24】若所有参数皆需类型转换,请为此采用non-members函数
1.令class支持隐式类型转换,往往是个糟糕的主意.但有些情况是合理的,比如数值类型.考虑,有理数Rational有分子,分母两个字段,缺省参数值为0,1.Ration a = 2;我们期望构造一个 ...
- 读书笔记_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函数
首先还是下面这个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:安全,量大,不缓存)( ...
随机推荐
- 关于fragment点击穿透的问题
当一个activity有多个fragment的时候,点击当前显示的fragment,如果点击处在其他fragment中也有相应的控件,那么可能会点击穿透,有响应另外fragment事件的趋势.但是这个 ...
- git源码阅读
https://github.com/git-for-windows/git/issues/1854 https://github.com/git-for-windows/git/pull/1902/ ...
- 项目中同一个dll的x86和x64同时引用
<ItemGroup Condition=" '$(Platform)' == 'x86' "> <Reference Include="System. ...
- SPA (单页应用程序)
单页Web应用 编辑 单页Web应用(single page web application,SPA),就是只有一张Web页面的应用.单页应用程序 (SPA) 是加载单个HTML 页面并在用户与应用程 ...
- Ubuntu 14.04 安装 qemu
参考: Ubuntu 12.04之找不到Qemu命令 Ubuntu 14.04 安装 qemu 安装: sudo apt-get install qemu 使用ln命令建立软连接: sudo ln - ...
- 使用caffe训练自己的图像数据(未完)
参考博客:blog.csdn.net/drrlalala/article/details/47274549 1,首先在网上下载图片,猫和狗.直接保存下载该网页,会生成一个有图片的文件夹.caffe-m ...
- HDU 6156 Palindrome Function
http://acm.hdu.edu.cn/showproblem.php?pid=6156 题意:$f(n,k)$表示判断n在k进制下是否是回文串,如果是,则返回k,如果不是,则返回1.现在要计算$ ...
- 基于R进行相关性分析--转载
https://www.cnblogs.com/fanling999/p/5857122.html 一.相关性矩阵计算: [1] 加载数据: >data = read.csv("231 ...
- GBDT 简述
GBDT 全称 Gradient Boosting Decision Tree,梯度提升决策树. 梯度增强决策树的思想来源于两个地方,首先是增强算法(Boosting),然后是梯度增强(Gradien ...
- git 代码冲突处理
在使用git pull代码时,经常会碰到有冲突的情况,提示如下信息: error: Your local changes to 'c/environ.c' would be overwritten b ...