1 大型对象
我们将Complex的运算符都定义为以类型Complex为参数,对于Complex运算符,各个运算对象都需要复制。然而对于大型对象来说,复制时的开销是很恐怖的,所以为了避免过度复制,我们有两个解决办法:
1 定义以引用为参数的函数。
例如:
class Matrix{
public:
friend Matrix operator(const Matrix &,const Matrix &);
};
引用时我们能对大型对象使用所涉到各种常见运算符的表达式,而又能避免过度复制。在这里不能使用指针,因为不能针对指针重定义运算符的意义。返回值是对象的引用,看起来合法,并且更加有效,然而这样做却会带来存储分配问题。一个结果的引用将被函数作为到返回值的引用传出来。这个返回值不能是自动变量,因此解决上述问题我们可以使用下面一种方法。
2 采用一个静态对象缓冲区,避免复制结果。
const int Max_size = 10;
Matrix &get_Matrix(){
static int nbuf = 0;
static Matrix buf[Max_size ];
if(nbuf == Max_size )nbuf = 0;
return buf[nbuf++];
}
Matrix & operator + (const Matrix &arg1,const Matrix & arg2){
Matrix &res = get_Matrix();
//............
return res;
}
现在只有表达式的结果赋值时需要复制Matrix,当然,要是写出一个表达式,其中涉及临时变量多余Max_size ,只有老天能帮你了。
2两个有意思的东西
1 间接
间接运算符->可以被定义为一个一元的后缀运算符。直接看例子:
class X{
public:
int m;
};
class ptr{
X *tmp;
public:
//.........
X* operator->(){
return tmp;
}
void f(ptr p){
p->m = 7; //(p.operator->())->m = 7;
}
};
看上去m就跟ptr的成员一样,是不是很有意思?
2 另一个很有意思的事情是如何实现a**b等价于a的b次方
上面的式子可以这样看 a*(*b)。
class B{
int a1;
public:
friend int operator *(B &tmp){
return tmp.a1;
}
};
class A{
int a2;
public:
operator int(){return a2;}
friend int operator *(int a, int b){
return pow(a,b);
}
};
A a;
B b;
a ** b //a的b次方
有意思归有意思,但是不推荐这样做。因为这样做了会造成代码的阅读困难,在重载运算符的时候,我们最好不要有违它原来的意思。
最后
本文并没有介绍各种运算符的具体重载办法,而侧重于运算符重载编程中应该注意的东西,所以不适合没有代码经验基础的人阅读。如果你也跟我一样,对敲代码有浓厚的兴趣,欢迎讨论。