- 哪些操作符不能被重载
. ?: :: .* sizeof
由于一些历史原因,?:不能被重载。若重载expr1 ? expr2 : expr3,不能确保expr2或expr3中只有一个被执行。
sizeof是内嵌操作符,某些操作符依赖它的实现,故不允许重载。
域描述符::两边不是对象或表达式,而是供编译器识别的名称。
::
performs a (compile time) scope resolution rather than an expression evaluation.
- 程序员能自行定义操作符吗?
不能。
这并不是一个语言技术上的难题,而是重载后表达式的内容使用者无法统一意见,这容易导致严重的问题。
eg:
**表示指数操作,对于a**b**c表示(a**b)**c还是a**(b**c),专家们的意见无法统一。
- 操作符重载原则
- 按照日常使用习惯重载,便于用户使用;
- 数学运算操作符应符合运算原理;
- 数学运算操作符必须具有实际意义时才能提供;
- 混合类型数学运算符也必须具有实际意义时才能提供;
- 若定义constructive operators,最好通过值返回;
- 若定义constructive operators,最好不要修改操作数;
- 若定义constructive operators,最好允许做操作数的类型提升;
- In general, your operator should change its operand(s) if and only if the operands get changed when you apply the same operator to intrinsic types.
- 若自定义x++,++x和x+=操作符,必须使其符合一般规则;
- 若定义pointer-like objects,*p, p[i], *(p+i)必须符合一般使用规则;
- 下标操作符一般需要成对出现(const和非const版本);
- 若定义x==y,有且只有这两个对象behaviorally equivalent时返回true;
- 若定义大小比较操作符,则间接比较与直接比较结果应保持一致;
- 避免会误导使用者的操作符重载。
constructive operators指那些计算后能构造新对象的操作符。
x++
and
++x
should have the same observable effect on
x
, and should differ only in what they return.
++x
should return
x
by reference;
x++
should either return a copy (by value) of the original state of
x
or should have a
void
return-type.
- 矩阵类的下标操作(subscript operator)符如何重载
使用operator()而不是operator[]。因为后者只能接收一个参数,而前者可以接收任意数量的参数。
double& operator() (unsigned row, unsigned col); // Subscript operators often come in pairs
double operator() (unsigned row, unsigned col) const; // Subscript operators often come in pairs
对于二维矩阵使用operator[]访问,实际上是通过Operator[]返回一个对象数组的引用,然后再通过operator[]返回二维矩阵元素对象。
The array-of-array solution obviously works, but it is less flexible than
the
operator()
approach
. Specifically, there are easy performance tuning tricks that can be done with the
operator()
approach that are more difficult in the
[][]
approach, and therefore the
[][]
approach is more likely to lead to bad performance, at least in some cases.
the
operator()
approach is never worse than, and sometimes better than, the
[][]
approach.
m(i,j)
gives you a clean, simple way to check all the parameters and to hide (and therefore, if you want to, change) the internal data structure.
- 如何重载前缀、后缀操作符
通过一个隐藏的参数。
class Number {
public:
Number& operator++ (); // prefix ++
Number operator++ (int); // postfix ++
};
注意:前缀版本返回引用;后缀版本返回值(或void)。因为后缀版本赋值内容是修改前的值,而此时this内容已经发生改变。