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

C++:类————运算符重载、友元函数

2015-02-04 10:36 211 查看
一、运算符重载

>1.什么是运算符重载:

类似于函数重载,运算符重载是C++多态的一种形式,允许程序员一些运算符用于自己制定的数据类型。

>2.为什么要进行运算符的重载:

举一个简单的例子,加入说要将两个数组想加,通常如下:

for(int i = 0 ; i < array_size ; ++i){
c[i] = a[i] + b[i];
}
但是借由对“+”运算符的重载,可以直接这样写:

c = a + b;
十分方便也更加直观,强调加法的实质而忽略其内部的详细操作,这是OOP的目标之一。

>3.运算符重载的语法:

统一的格式如下:

operator sign (argument_list)
其中sign表示某一种运算符的符号。

一般来说,都是在类的成员函数中声明,在另一个文件中进行定义(和普通的成员函数的定义方式完全相同)。

其实,可以将operator sign整体看做一个函数名,只是它的结合方式不同而已。

例如定义了一个名为Time的Class,t1,t2,t3都是Class的对象,对加法进行了如下重载:

class Time()
{
private:
minutes;
hours;
public:
...
...
Time operator + (const Time & t)const;
....

};


Time Time:: operator + (const Time & t) const
{
Time sum;

sum.minutes = minutes + t.minutes;
sum.hours = hours + t.hours + sum.minutes / 60;
sum.minutes %= 60;
}
那么语句t3 = t1 + t2就相当于t3 = t1.operator + (t2)

在这里需要强调的是,成员符号".“操作符的结合方式总是自左向右的,如果写t3 = t2 + t1,虽然结果相同,但是实际上是这样调用的 t3 = t2.operator + (t1),此处十分重要。

>4.运算符重载的注意事项:

重载后的运算符必须至少有一个操作数是用户自定义型的,这将防止用户重载标准运算符。

使用运算符不可以违背原来的句法规则,例如%是对两个操作数使用的,不可以出现形如%x的重载

不可以修改运算符的算数优先级

不可以通过重载创建新的运算符

可以通过成员函数(在类内部)或者非成员函数(和普通函数一样,在类的外部)重载,但是有一些运算符"=,(),[],->"只能在成员函数里进行重载

二、友元函数

>1.什么是友元函数

通过让函数称为类的友元,可以赋予该函数同成员函数一样的权限去访问类的私有成员。

>2.为什么要使用友元函数

这里需要举一个直观的例子:

A = B + 50.0(其中A、B是同一种类的对象),这里我们假设对+进行了重载,那么该语句相当于:

A = B.operator + (50.0) (再次强调运算符左侧的操作数是调用对象)

按照运算符左侧是调用对象的规则,A = 50.0 + B 是错误的,因为50.0不是一个对象,这就让我们有点不开心了。

解决访问有两个:一是强制要求大家都写成A = B + 50.0 的形式,这大家肯定非常不开心;二是将重载定义为成非成员函数的形式(即相当于一个普通的函数),非成员函数 的重载的调用规则是将 A = 50.0 + B 与 A = operator + (50.0,B)的等价,这样可以。

但是非成员函数有一个非常大的缺点,不可以访问对象的私有成员,怎么办呢?这时候就由友元函数出马了。

>3.创建友元函数

创建友元函数的第一步是将其原型放在类的声明中,并在声明的前边加关键字friend

friend Time operator + (double m,const Time & t);
这个原型意味着虽然函数operator + ()是在类中声明的,但是它不能被成员运算符来调用,但是享有和成员函数一样的权利,访问TIme类的私有成员。

第二步就是编写定义,由于友元函数不是成员函数,所以定义中不需要加限定符,这个例子中意思是无需写 Time::,所以定义应该如下:

Time operator + (double m,const Time & t){
.......
}
>4.常用的友元函数

最为常用的友元函数应该就是operator << ()了,对<<进行重载大大方便了编写输出时的代码。

void operator << ( ostream & os,const Time & t){
os << t.hours << " hours " << t.minutes << " minutes " << endl;
}


因为参数按照从左往右的顺序填入,这样语句cout << time 就相当于 operator + (cout,time)

其中os是cout的一个引用,可以使用这种方式。

这里需要说明的是,operator<<()直接访问Time类的私有成员但是不访问ostream类的私有成员,因此它是类Time的友元而不是ostream的友元。

但是这个版本实际上和我们常用的有很大差别,因为不能够 cout << time1 << time2 <<...这样写,实际上我们都知道 cout << time1会返回一个ostream类的对象,才能够继
续使用<<这个符号,因此,我们应当对上述代码改进一下:

ostream &  operator << (ostream & os,const Time & t){
os << t.hours << " hours " << t.minutes << " minutes " << endl;
return os;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐