Re: [问题] 关于运算子重载(operator overloading)

楼主: Feis (永远睡不着 @@)   2015-05-24 23:34:03
※ 引述《wtchen (没有存在感的人)》之铭言:
: 问题(Question):
: 目前正在写一个可以进行加减乘除的大数class。
: 有一个关于operator overloading的问题:
: 据我所知可以使用method(写在class里面)或function(class外面)
: 请问一般情况下使用method还是function好呢?
: 我想要overload的operator包括
: +, -, *, /, +=, -/, *=, /=, %
: 目前我唯二知道需要用function解决的有两种情况:
: - operator 作用于 class 跟另一种 class
: ex: Complex a; double b; Complex c = a * b;
: - 需要用到cout <<
: ex: Complex a(1,1); cout << a << endl;
: 谢谢。
就 C++ 而言,在成员或非成员函式取舍时我的想法大概是这样的顺序:
1. 语法限制: 有些情况下你根本没得选
情况一: operator=, operator[], operator() 和 operator-> 在标准规定是不能用
非成员函式多载。此时只能用成员函式。
情况二: 当你为二元运算子时,如果左算子的类别定义无法更改。例如你提到
cout << a; 。此时只能用非成员函式。
情况三: 当你为一元运算子时,如果算子为 enum 型态,此时只能用非成员函式。
2. 安全考量: 避免隐性转型。
情况: 当你为二元运算子时,如果左算子为内建型态或 enum,则优先使用非成员
函式。
3. 封装考量: 一般非成员函式的优点在于保证其无法存取私有成员。所以从封装来看,
如果可以的话,非成员函式应该优先。
问题发生在当我们需要存取私有成员时会有两个选择: 一个是使用成员函
式,另一个则是使用 friend 的非成员函式。
情况一: 如果是一元运算子,或者是二元运算子但是两个算子的类别相
同时,我倾向用成员函式。主要是因为从属性蛮明确的。
情况二: 如果是二元运算子且两个算子的类别不同。则此时看其两运算
元角色是否一样,例如其是否遵守交换律,也就是两个算子交
换位置是否会得到一样的结果。如果遵守交换律我会选用非成员
函式 (加 friend),反之则通常是因为会修改到左算子的内容
(例如 operator +=),此时我会使用成员函式。当然其他情况
就看自己觉得哪个合理 Orz.
依照我的想法,原 po 的 +, - , *, /, % 我会用非成员函式, +=, -=, *= 和 /= 会
用成员函式。不过我相信每个人看法一定有所差异。
作者: azureblaze (AzureBlaze)   2015-05-24 23:41:00
就封装而言“非成员非friend”是比较好的挂了个friend上去他的存取权就跟成员没两样了
楼主: Feis (永远睡不着 @@)   2015-05-24 23:46:00
此外原 po 也可能参考 std::complex http://goo.gl/yOCkb3*可以参考发现自己少写了一个情况. 补了一下二元运算子但类别一样的
作者: wtchen (没有存在感的人)   2015-05-25 01:41:00
问个问题,当二元运算子跟非同类别之物件作用时例如complex a, double b, complex c = a*b跟complex c = b*a结果会一样吗?我是说只要用非成员函式就会自动遵守交换律吗(有点搞混状态)
作者: LPH66 (-6.2598534e+18f)   2015-05-25 01:51:00
Feis 说的是语意上的交换律, 编译器永远当被 overload 的operator 是不可交换的
作者: wtchen (没有存在感的人)   2015-05-25 02:08:00
所以若我要让交换律成立,我得写两个非成员函式?const complex operator*(double a, BigNumber& b)和const complex operator*(BigNumber& b, double a) ?(抱歉,BigNumber是我正在写的大数物件)
作者: LPH66 (-6.2598534e+18f)   2015-05-25 04:06:00
你要直接写确实是这样没错, 不过这里如我前篇推文说的一般来说会写 BigNumber(double) 以及BigNumber operator* (const BigNumber&,const BigNumber&)让编译器碰到这种状况时先用前者建立暂时 BigNumber 物件再使用后者进行计算, 这样同一段程式就不用写两次然后, operator* 一般会再使用 operator *= 来写同样也是为了同一段程式不用写两次这时的 operator* 会变成用传值进来再直接 *= 后回传

Links booklink

Contact Us: admin [ a t ] ucptt.com