假设有一个有理数类Rational,有一个计算有理数乘法的成员函数operator*,示例如下:

 #include <iostream>

 class Rational
{
public:
Rational(int numerator = , int denominator = )
{
n = numerator; // 分子
d = denominator; // 分母
}
int numerator() const
{
return n;
}
int denominator() const
{
return d;
}
const Rational operator*(const Rational& rhs) const
{
return Rational(this->n * rhs.n, this->d * rhs.d);
} private:
int n;
int d;
}; int main()
{
Rational oneEight(, );
Rational oneHalf(, );
Rational result1 = oneEight * oneHalf; // 同类型运算
34 Rational result2 = oneHalf * 3; // 混合运算1
35 Rational result3 = 3 * oneHalf; // 混合运算2  
std::cout << result1.numerator() << "/" << result1.denominator() << std::endl;
std::cout << result2.numerator() << "/" << result2.denominator() << std::endl;
std::cout << result3.numerator() << "/" << result3.denominator() << std::endl; return ;
}


如上可见,该乘法运算对于执行同类型运算没有任何问题,为什么对于执行混合运算却有时可以,有时又不可以呢?其实,我们知道执行oneHalf * 3时,编译器调用oneHalf的成员函数,然后对于3执行隐式类型转换(调用Rational的构造函数完成的),转换为Rational后执行乘法运算,因此没出现错误;但是对于3 * oneHalf而言就不同了,因为3并没有相应的成员函数,因此,编译器将试图寻找non-member operator*:result = operator*(2, oneHalf),但是很遗憾,你没有提供这样的函数,因此发出错误。因此结论是:像这种需要发生类型转换才能继续工作的函数,你必须提供一个non-member函数来完成工作,示例如下:

 const Rational operator*(const Rational& lhs, const Rational& rhs)
{
return Rational(lhs.numerator() * rhs.numerator(), lhs.denominator() * rhs.denominator());
}


这样的话上述的两种混合调用方式都可以通过了。因此请记住如下结论:

当你设计的某个函数的所有参数(包含this指针所指的那个隐含参数)都可能需要发生类型转换时,那么这个函数必须是non-member函数。

条款24:若所有的函数参数可能都需要发生类型转换才能使用,请采用non-member函数的更多相关文章

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

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

  2. 深入理解javascript函数参数与闭包(一)

    在看此文章,希望先阅读关于函数基础内容 函数定义与函数作用域 的章节,因为这篇文章或多或少会涉及函数基础的内容,而基础内容,我放在函数定义函数作用域 章节. 本文直接赘述函数参数与闭包,若涉及相关知识 ...

  3. C++数组(指针)作为函数参数

    本文的学习内容参考:http://blog.csdn.net/wwdlk/article/details/6322843 1.当用数组名作为函数参数时,函数的实参和形参都应为数组名(或者指针): Ex ...

  4. php的函数参数按照从左到右来赋值

    PHP 中自定义函数参数赋默认值 2012-07-07 13:23:00|  分类: php自定义函数,默|举报|字号 订阅     下载LOFTER我的照片书  |     php自定义函数接受参数 ...

  5. Day8 函数指针做函数参数

    课堂笔记 课程回顾         多态 virtual关键字 纯虚函数 virtual func() = 0;         提前布局vptr指针 面向接口编程 延迟绑定 多态的析构函数的虚函数. ...

  6. Java获取函数参数名称

    原理 编译之后的class文件默认是不带有参数名称信息的,使用 IDE 时,反编译jar包得到的源代码函数参数名称是 arg0,arg1......这种形式,这是因为编译 jar 包的时候没有把符号表 ...

  7. python 函数参数的传递(参数带星号的说明) 元组传递 字典传递

    python中函数参数的传递是通过赋值来传递的.函数参数的使用又有俩个方面值得注意:1.函数参数是如何定义的 2.在调用函数的过程中参数是如何被解析 先看第一个问题,在python中函数参数的定义主要 ...

  8. pyhton 函数参数,递归函数,高阶函数(一点点笔记)

    '''def test(x,y): print(x) print(y)test(2,y=3)def test(*args):#参数可以是不确定的多个数,接受N个位置参数,转换成元组形式 print(a ...

  9. ES6函数参数默认值作用域的模拟原理实现与个人的一些推测

    一.函数参数默认值中模糊的独立作用域 我在ES6入门学习函数拓展这一篇博客中有记录,当函数的参数使用默认值时,参数会在初始化过程中产生一个独立的作用域,初始化完成作用域会消失:如果不使用参数默认值,不 ...

随机推荐

  1. centos下的防火墙配置

    1,查看防火墙文件: vim /etc/sysconfig/iptables # Generated by iptables-save v1. :: *filter :INPUT ACCEPT [:] ...

  2. vyatta的fork开源版本

    https://www.reddit.com/r/networking/comments/3dvwfy/who_here_is_using_vyos/ Vyatta came in two flavo ...

  3. jQuery遍历 slice()方法

    今天做页面,遇到一个滚动的swipe,需要4个<li> 一组,然后在外层加个<ul>,方法如下: $('.xxxxx li').each(function(n){ $('.xx ...

  4. 【MySQL】MySQL无基础学习和入门之一:数据库基础概述和实验环境搭建

    数据库基础概述  大部分互联网公司都选择MySQL作为业务数据存储数据库,除了MySQL目前还有很多公司使用Oracle(甲骨文).SQLserver(微软).MongoDB等. 从使用成本来区分可以 ...

  5. Something wrong with EnCase index search in Unallocated area

    hi, My EnCase version is v7 and I found a terrible issue about index search in Unallocated area. Wit ...

  6. 二十、ValueStack的常用方法

    二十.ValueStack的常用方法 void set(String key,Object value):先获取根栈栈顶的Map,如果不存在,压入一个新的Map public String execu ...

  7. iOS 获取当前城市

    1.倒入头文件 #import <CoreLocation/CoreLocation.h> 2.实现定位协议CLLocationManagerDelegate 3.定义定位属性  @pro ...

  8. linux安装桌面环境(GNOME)VNC连接Linux

    1.安装Gnome桌面 这里是使用的脚本安装.代码如下:  加附件 #!/bin/sh #This script is FREE and written by www.vpsyou.com   # i ...

  9. Stop PeopleCode Processing with Error

    A blunt, but useful method for debugging PeopleCode is to use the inbuilt "Error" function ...

  10. 例题6-10 The Falling Leaves,UVA699

    这道题我的思路是先通过递归构建树,然后进行遍历将位置和保存在map映射中,最后按顺序输出map集合中的值. 至于如何遍历,我是依次尝试了宽度优先遍历和深度优先遍历,当然这都是可以的.不过期间写错了很多 ...