【C/C++学习】之十三、运算符重载

所有一元运算符         建议重载为成员函数
= () []  —>         只能重载为成员函数
+= -= /= *= |= ~= %= >>= <<=   建议重载为成员函数
所有其他运算符         建议重载为全局函数
. 操作符不能重载

不能重载目前C++运算符集合中没有的符号   

 原因:1。难以理解   2.难以确定优先级

对已经存在的运算符进行重载时,不能改变优先级规则,否则将引起混乱。

运算符重载的一般形式如下:

返回类型 operator 运算符符号(参数说明)
{
....
}

函数重载的时候,只有一个参数的运算符叫做一元运算符,有两个参数的运算符叫做二元运算符。

当你在类中重载运算符的时候,如果是一元运算符就不需要参数了,二元运算符只有一个右侧参数,因为对象自己就作为左侧参数。

对于全局函数和成员函数:

运算符

建议

所有的一元运算符 建议重载为成员函数                                 
=、()、[]、-> 只能重载为成员函数
+=、-=、/=、*=、&=、|=、~=、%=、>>=、<<= 建议重载为成员函数
所有其他运算符 建议重载为全局函数

下面看一下重载运算符的规则:

1、只能重载语言自身已有定义的运算符。

2、有5个运算符不能重载,分别是类属性运算符“."、成员指针运算符”*“、作用域分辨符"::"、”sizeof“运算符和三目运算符"?:'。  还有就是不能重载C++运算符集合中没有的符号,因为他们难以理解,难以确定优先级。

3、不能改变运算符的操作个数。

4、不能改变运算符的原有优先级。

5、不能改变运算符原有的结合特性。

6、不能改变运算符对预定义类型数据的操作方式。

{优先级不变,结合性不变,操作数不变,语法结构不变}

在类中,有成员函数和友元函数两种,我们可以使用友元函数重载运算符。也就是当操作符定义为非成员函数时,通常必须将他们设置为所操作类的友元。

当我们使用友元函数重载运算符时,由于没有this执着呢,因此,函数的参数是引用类型:

A operator +(const A &a1, const A &a2);

当我们使用友元函数重载双目运算符时,两个操作数都要传递给运算符函数。

当我们使用友元函数重载单目运算符时,需要一个显示的操作符。

我们在实际开发中,单目运算符建议重载为成员函数,而双目运算符建议重载为友元函数,通常情况下双目运算符重载为友元函数比重载为成员函数更方便,但是有时双目运算符必须重载为成员函数:如:赋值运算符,  如果将该运算符重载为友元函数,将会出现与赋值予以不一致的地方。

但是当我们用友元函数重载”++“和”--“运算符的时候又会怎样呢?

          运算符”++“和”--“都是对单值操作数产生影响的,因此使用成员函数重载这两个运算符的成员函数通常返回指针this。

          因为友元函数没有this指针,因此不能引用this指针作为指向的对象。使用友元函数重载这两个操作符时,应采用引用参数传递数据。

如:

a operator ++(a &op)
{
    ++op.x;
    ++op.y;
     return op;
}

说到这里,我们就来看一下成员运算符函数和友元运算符函数的区别:

1、格式不同

友元函数:

<类型说明符> operator <运算符>(<参数表>)
{
函数体
}
成员函数:

<类型说明符> 类名::operator <运算符>(<参数表>)
{
函数体
}

2、参数表的结构不同

在成员运算符函数的参数表中,如果运算符时单目的,则参数为空,此时当前对象作为运算符的一个操作数,通过this指针隐含地传递给函数;

如果运算符时双目的,则参数表中有一个操作数,该操作数作为运算符的右操作参数,此时当前对象作为运算符的左操作数,它是由this指针隐含地传递给函数的。

而和成员函数不同,友元运算符函数不属于任何类对象,其没有this指针。如果重载的是双目运算符,则参数表中有两个操作数;如果重载的是单目运算符,则参数表中只有一个操作数。

 


下面来看一下重载NEW和DELETE运算符,数组下标运算符:

1、NEW和DELETE运算符

有两种方式重载:

1、覆盖默认定义的全局方式    2、只针对一个类的局部方式。      在实际应用中,一般采用后一种方式。

void* operator new(size_t size)
{
使用new运算符分配size大小的存储空间。
}

void* operator delete(void* pointer)
{
使用delete运算符释放指针pointer所指向的存储空间
}

上面是new和delete运算符的重载方式, 其中pointer指针指向一个待释放的内存空间,   我们调用delete()函数释放该指针所指向的内存空间。

我们在类中重载的new和delete运算符只能用于动态生成各个对象,而不能用于生成对象数据、自动对象和静态对象等。

重载全局的new和delete运算符需要在类的外部定义,定义格式与在类中定义的格式基本相同,只是不带类作用域。重载全局的new和delete运算符时需要谨慎,一旦定义为全局,在整个程序中只要是使用new和delete运算符的操作都将使用该重载的定义。


2、数组下标运算符

我们知道数组的大小是不能确保的,所以对数组元素进行存取范围的检查是不允许的,所以在操作数组动态赋值时经常会发生越界。所以我们在这里来说一种安全的方案定义重载的运算符"[]";

我们在重载下标运算符的时候要注意:

1、该函数只能带一个参数,不能带多个参数。

2、得重载为友元函数,必须是非static类的成员函数。


下面再来看一下重载输入输出操作符:

ostream& operator<<(ostream& out, const A& s)
{
    out  << s.a  <<.............
    return out;
}


instream& operator>>(istream& in, A& s)
{
    double si;
    in >> s.a.....................
    if (in)
        ...
    else
        ...
    return in;
}



最后要注意的是不要滥用操作符重载。



2012/10/11

jofranks 于南昌

原文地址:https://www.cnblogs.com/java20130723/p/3211391.html