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

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

 1 #include <iostream>
 2
 3 class Rational
 4 {
 5 public:
 6     Rational(int numerator = 0, int denominator = 1)
 7     {
 8         n = numerator;              // 分子
 9         d = denominator;            // 分母
10     }
11     int numerator() const
12     {
13         return n;
14     }
15     int denominator() const
16     {
17         return d;
18     }
19     const Rational operator*(const Rational& rhs) const
20     {
21         return Rational(this->n * rhs.n, this->d * rhs.d);
22     }
23
24 private:
25     int n;
26     int d;
27 };
28
29 int main()
30 {
31     Rational oneEight(1, 8);
32     Rational oneHalf(1, 2);
33     Rational result1 = oneEight * oneHalf;  // 同类型运算
34     Rational result2 = oneHalf * 3;         // 混合运算1
35     Rational result3 = 3 * oneHalf;         // 混合运算2  
36
37     std::cout << result1.numerator() << "/" << result1.denominator() << std::endl;
38     std::cout << result2.numerator() << "/" << result2.denominator() << std::endl;
39     std::cout << result3.numerator() << "/" << result3.denominator() << std::endl;
40
41     return 0;
42 }


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

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


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

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

时间: 2024-11-03 21:26:58

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

Python中的函数参数

在讲函数参数之前还是简单的讲一下Python中的可变对象与不可变对象. 一.可变对象与不可变对象 在Python中,一切皆对象,python中不存在所谓的传值调用,一切传递的都是对象的引用,也可以认为是传址.所谓可变对象是指,对象的内容可变,而不可变对象是指对象内容不可变(即在其创建后,值不能改变,但可创建新的对象并以同一变量名对其赋值,而旧的对象会被清理掉,这在python里叫对象的垃圾收集).不可变(immutable):int.字符串(string).float.(数值型number).元

Day8 函数指针做函数参数

课堂笔记 课程回顾 多态 virtual关键字 纯虚函数 virtual func() = 0; 提前布局vptr指针 面向接口编程 延迟绑定 多态的析构函数的虚函数. 多继承的二义性 . 重载 重写 重定义. 实现多态的理论基础:函数指针做函数参数. vptr指针与虚函数表. 构造函数不应为虚函数 多态会降低程序的执行速度.不建议所有的函数都是虚函数. 多态时的指针步进. 多继承在项目开发中使用的比较少. linux从2.4内核升级到2.6的时候,做到了电源可以热插拔,提前将电源驱动的接口规划

关于ECMAScript函数参数的多方面理解

写在前面 无论在哪种编程语言中,函数都是特别有意思的部分,但同时也是一个难点.在ECMAScript中,作为对象的函数也不例外,让人又爱又恨.这一章我们主要从多个方面聊一聊函数参数这一部分,至于函数像海一样深的其他部分我们有机会再聊. 函数的有些知识点是比较简单的,所以在进入正题之前,我们先简单介绍两点:函数的return和函数的重载,因为函数的重载需要arguments的知识,所以我们最后来理解函数的重载. 章节结构如下: 函数的return 函数参数 函数的重载 注:如没有另外说明,文中的函

转:python 函数参数的传递(参数带星号的说明)

python中函数参数的传递是通过赋值来传递的.函数参数的使用又有俩个方面值得注意:1.函数参数是如何定义的 2.在调用函数的过程中参数是如何被解析 先看第一个问题,在python中函数参数的定义主要有四种方式:1.F(arg1,arg2,...)这 是最常见的定义方式,一个函数可以定义任意个参数,每个参数间用逗号分割,用这种方式定义的函数在调用的的时候也必须在函数名后的小括号里提供个数相等的 值(实际参数),而且顺序必须相同,也就是说在这种调用方式中,形参和实参的个数必须一致,而且必须一一对应

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

一.函数参数默认值中模糊的独立作用域 我在ES6入门学习函数拓展这一篇博客中有记录,当函数的参数使用默认值时,参数会在初始化过程中产生一个独立的作用域,初始化完成作用域会消失:如果不使用参数默认值,不会产生这个作用域:产生疑问是因为这段代码: var x = 1; function foo(x, y = function () {x = 2;}) { var x = 3; y(); console.log(x); }; foo();//3 foo(4);//3 console.log(x);//

条款23:宁以non-member, non-friend,替换member函数。

考虑下面这种经常出现的使用方式: class webBroswer{ public: ... void clearCache(); void clearHistory(); void removeCookies(); ... }; 那么很自然的就会想到增加这么一种清理方式: class WebBrowser{ public: ... void clearEverything(); }; 或者是这么一种清理方式: void clearBrowser(WebBrowser & wb) { wb.cl

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

(一) 假设一个class用来表现有理数,允许整数"隐式转换为"有理数似乎很合理. class Rational{ public: Rational(int numerator = 0, int denominator = 1); //刻意不为explicit:允许int-to-Rational隐式转换 int numerator()const; int denominator()const; }; 在支持算术运算符时考虑该由member函数.还是non-member函数来实现: (1

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

1. 通常,将只接受拷贝构造函数声明为explict是一个不错的主意,因为这可以避免自动的隐式类型转换所带来的错误,但有些情况下,使类支持隐式类型转换是可行的,例如自定义的数值类型: class Rational{ public: Rational(int numerator=0,int denominator=1); int numerator()const; int denominator()const; private: int numerator; int denominator; }

《Effective C++》学习笔记——条款24

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 四.Designs and Declarations Rule 24:Declare non-member functions when type conversions should apply to all parameters 规则 24:若所有参数皆需类