您的位置:首页 > 编程语言 > C语言/C++

关于C++运算符的重载

2007-04-23 16:34 281 查看
C++运算符的重载,为C++提供了可扩展性,这也是C++最吸引人的属性之一。在完成同样的操作的情况下,如果运算符重载能够比用明确的函数调用使程序更清晰,则应该使用运算符的重载。

从本质上讲,我始终认为运算符的重载本身也是类的一个成员函数,只不过这个成员函数的写法不可以按照自己的意愿随意的起名字,要按照C++语法规范来写,不过就运算符本身的实现来看,似乎真的和函数没有什么两样。

关于C++运算符的操作,任何一本C++书中都会有清楚的交代,这里不说了,一篇博客估计也说不清楚,这里着重谈几个问题,这几个问题是几年前初学C++时困扰我的,有机会写出来,希望对新的初学者有所帮助。

1,重载“=”时,需要返回值么,返回值为什么要是const呢?

如果 有一个Array的类,现在需要重载它,一般C++ 的入门书上都是这么声明的

const Array& operator=(const Array &)

重载完这个函数之后,下面的操作就显得顺理成章了

Array a , b , c ;

//对a进行初始化

b = a ;

c = a ;

从函数的角度来看,b=a可以看成是一种函数的调用,函数名称是“operator=”,输入的参数是a,有的人可能顺理成章的认为返回值就是b了吧。咋一看,这似乎也解释的通,但是,要注意的是这个函数“operator=”本身是一个类的函数,类的函数必然用类的实力化对象来调用,如果返回值是b,那么是谁调用了函数“operator=”呢?从这个角度上讲,返回值绝对不是b,b实质上就是那个实例化的对象。

那么有人可能会说,既然这样,那么为什么还要有返回值呢?

返回值,不是用来对b赋值的,上面的声明写成如下形式,也完全正确

void operator=(const Array &)

但是,教科书绝对不会画蛇添足的,之所以要返回值,是有原因的。

如果把上面的赋值代码写成这个样子

b = c = a ;

那么你如果还用void operator=(const Array &),编译就会报错了,因为在上面这个式子里面,函数仍然是“operator=”,输入参数是“c=a”,调用这个函数的实例化对象是b,那么如果再次分解“c=a”

,就不难看出,因为c =a的返回值是void,而b调用的函数“operator=”是要求const Array &的,参数类型不匹配,必然报错。

那么如果我们把=的重载写成

Array & operator=(const Array &)的形式是不是就对了呢?

对于b=c=a,这条语句而言,足够了,不过如果我们把这条语句不小心写成

(b=c)=a,那么如果没有加上const,程序是不会报错的,当然一般也不可能写成这种形式了,所以在一些教科书上,有时也会看到没有const的返回值形式。

2. 关于二维数组类,运算符[ ] 的重载

我上面举的Array的例子,相信大多数的C++ 书籍在讲运算符重载的时候,都会提到,在书里面应该也重载了运算符[ ],书中是这样写的

int & operator[ ](int subscript)紧跟着下一行,会写

const int& operator[ ](int subscript),不过我在VC6.0下,无论是写aArray[1] = 1 ;还是写bArray[1] = aArray[1],跟踪调试,函数都没有跳到第二个[ ]重载运算符中,不知道是不是理解的还是有问题。

这里我想说的是,如果对于一个和二维数组对应的类,那么运算符[ ][ ]应该怎么重载呢?

事实上,[ ][ ]并非有效的运算符,只有[ ] 才是合法的,其实可以这样写的(假设是二维整数数组类)

int* & operator[ ](int subscript)

{

return m_pp[subscript] ;

}

其中m_pp是一个指针的指针,他实际上就是一个二维数组的指针

在成员函数里,可以这样定义

int ** m_pp;

非配空间时,可以这样写

m_pp = new int*[height] ;

for(int j = 0 ; j < height ;++j

{

m_pp[j] = new int[widht] ;

}

这就初始化了一个height行×width列的二维数组.

3.VC7.0和VC8.0中的模板类友元函数

模板类友元函数必须声明template

举例说明:

#include <iostream>
using namespace std ;
template<class T>

class LinearList{
//VC7.0以后的版本中,友元函数要声明template<class T>的字样
template<class T> friend ostream& operator<<(ostream& out, const LinearList<T>& x ) ;

};

template<class T>
ostream& operator<<(ostream& out ,const LinearList<T>& x ){
//重载操作

return out ;
}

4,把一个重载的运算符声明为friend和声明为成员变量,有什么区别?

答案很简单,就是如果声明成friend,那么函数(这里的函数就是指运算符重载)的参数可以是两个,而声明为成员变量,那么函数参数只能是一个。如下两个写法都对:

public:

Array operator+(const Array& b) {

Array temp ;

// 应该是一个循环的,这里只是一个实例罢了

temp.value[i] = this->value[i] + b.value[i] ;

return temp ;

}

或者

friend

Array operator+(const Array& a , const Array& b) {

Array temp ;

// 应该是一个循环的,这里只是一个实例罢了

temp.value[i] = a.value[i] + b.value[i] ;

return temp ;

}

第二种写法中的参数a,就相当于第一种写法中的函数实现中的this。不过“=”不可以写成friend的形式,只能写为成员函数的形式。

一般来说,只把输入输出操作符<<和>>写成friend的形式,其余的全部写为成员变量的形式
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: