首页 > 编程笔记

C++运算符重载的用法和规则

C++ 的一大特性就是重载,重载使得程序更加简洁高效。在 C++ 中不只函数可以重载,运算符也可以重载,运算符重载主要是面向对象之间的。

在 C++ 中,运算符的操作对象可以是基本的数据类型,也可以是类中重新定义的运算符,赋予运算符新的功能,对类对象进行相关操作。在类中重新定义运算符,赋予运算符新的功能以适应自定义数据类型的运算,就称为运算符重载。

我们知道重载的运算符,如运算符+可以进行算术的加法运算,在 String 类中可以连接两个字符串;运算符>> 和 <<可以对数据进行右移和左移运算,在输入、输出流类中可以实现输入和输出操作。

本文将针对运算符重载的语法、规则和方式进行介绍。

C++运算符重载的语法

在 C++ 中,使用 operator 关键字定义运算符重载。运算符重载语法格式如下:

返回值类型 operator 运算符名称 (参数列表)
{
    ...//函数体
}

从运算符重载语法格式可以看出,运算符重载的返回值类型、参数列表可以是任意数据类型。除了函数名称中的 operator 关键字,运算符重载函数与普通函数没有区别。

【示例1】下面通过案例演示“+”“−”运算符的重载,C++ 代码如下:
#include<iostream>
using namespace std;
class A
{
private:
    int _x;
    int _y;
public:
    A(int x=0,int y=0):_x(x),_y(y){}
        void show() const;      //输出数据
        A operator+(const A& a) const;   //重载"+"运算符
        A operator-(const A& a) const;   //重载"-"运算符
};
    void A::show() const      //show()函数的实现
    {
        cout<<"(_x,_y)="<<"("<<_x<<","<<_y<<")"<<endl;
    }
    A A::operator+(const A& a) const    //重载"+"运算符的实现
    {
        return A(_x+a._x,_y+a._y);
    }
    A A::operator-(const A& a) const    //重载"-"运算符的实现
    {
        return A(_x-a._x,_y-a._y);
    }
    int main()
    {
        A a1(1,2);
        A a2(4,5);
        A a;
        cout<<"a1: "; 
        a1.show();
        cout<<"a2: "; 
        a2.show();
        a=a1+a2;        //实现两个对象相加
        cout<<"a: "; 
        a.show();
        a=a1-a2;        //实现两个对象相减
        cout<<"a: "; 
        a.show();
        return 0;
    }
运行结果:

a1: (_x,_y)=(1,2)
a2: (_x,_y)=(4,5)
a: (_x,_y)=(5,7)
a: (_x,_y)=(-3,-3)

示例分析:
通过上面讲解可以知道,重载运算符并没有改变其原来的功能,只是增加了针对自定义数据类型的运算功能,具有了更广泛的多态特征。

C++运算符重载的规则

上面我们讲解了运算符重载的语法格式,需要注意的是,有的运算符是不可以重载的,并且运算符重载不可以改变语义。

运算符重载的具体规则如下:

表1 可重载的运算符
+ - * / % ^ &
| ! , = < >
>= <= ++ -- « >> ==
!= && || += -= /= %=
^= &= != *= <<= >>= []
() -> ->* new new[] delete delete[]

C++运算符重载的形式

运算符重载一般有两种形式:重载为类的成员函数和重载为类的友元函数。下面分别对这两种形式进行详细讲解。

1) 重载为类的成员函数

重载“+”“−”运算符为类的成员函数,成员函数可以自由地访问本类的成员。运算的操作数会以调用者或参数的形式表示。

如果是双目运算符重载为类的成员函数,则它有两个操作数:左操作数是对象本身的数据,由 this 指针指出;右操作数则通过运算符重载函数的参数列表传递。

双目运算符重载后的调用格式如下所示:

左操作数.运算符重载函数(右操作数);

【示例1】中重载“+”运算符,当调用 a1+a2 时,其实就相当于函数调用 a1.oprerator+(a2)。

如果是单目运算符重载为类的成员函数,需要确定重载的运算符是前置运算符还是后置运算符。

如果是前置运算符,则它的操作数是函数调用者,函数没有参数,其调用格式如下所示:

操作数.运算符重载函数();

例如重载单目运算符“++”,如果重载的是前置运算符“++”,则 ++a1 的调用相当于调用函数 a1.operator++()。

如果重载的是后置运算符“++”,则运算符重载函数需要带一个整型参数,即“operator++(int)”,参数 int 仅仅表示后置运算,用于和前置运算区分,并无其他意义。

【示例2】为了加深读者的理解,下面通过案例演示前置运算符“++”与后置运算符“++”的重载。C++代码如下:
#include<iostream>
using namespace std;
class A
{
private:
    int _x;
    int _y;
public:
    A(int x=0,int y=0):_x(x),_y(y){}
    void show() const;   //输出数据
    A operator++();    //重载前置“++”
    A operator++(int);   //重载后置“++”
};
void A::show() const
{
    cout<<"(_x,_y)="<<"("<<_x<<","<<_y<<")"<<endl;
}
A A::operator++()     //前置“++”实现
{
    ++_x;
    ++_y;
    return *this;
}
A A::operator++(int)    //后置“++”实现
{
    A a=*this;
    ++(*this);     //调用已经实现的前置“++”
    return a;
}
int main()
{
    A a1(1,2), a2(3,4);
    (a1++).show();
    (++a2).show();
    return 0;
}
运行结果:

(_x,_y)=(1,2)
(_x,_y)=(4,5)

示例分析:
由运行结果可知,对象 a1 先输出结果后执行“++”运算,而对象 a2 先执行“++”运算后输出结果。

2) 重载为类的友元函数

运算符重载为类的友元函数,需要在函数前加 friend 关键字,其语法格式如下所示:

friend 返回值类型 operator 运算符(参数列表)
{
    ...//函数体
}

重载为类的友元函数时,由于没有隐含的 this 指针,因此操作数的个数没有变化,所有的操作数都必须通过函数的参数进行传递,函数的参数与操作数自左至右保持一致。

【示例3】下面通过案例演示将运算符“+”和“−”重载为类的友元函数,C++代码如下:
#include<iostream>
using namespace std;
class A
{
private:
    int _x;
    int _y
public:
    A(int x=0,int y=0):_x(x),_y(y){}
    void show() const;         //输出数据
    friend A operator+(const A& a1, const A& a2) ;    //重载为类的友元函数
    friend A operator-(const A& a1, const A& a2);     //重载为类的友元函数
};
void A::show() const
{
    cout<<"(_x,_y)="<<"("<<_x<<","<<_y<<")"<<endl;
}
A operator+(const A& a1,const A& a2)
{
    return A(a1._x+a2._x,a1._y+a2._y);
}
A operator-(const A& a1,const A& a2)
{
    return A(a1._x-a2._x,a1._y-a2._y);
}
int main()
{
    A a1(1,2);
    A a2(4,5);
    A a;
    cout<<"a1: "; 
    a1.show();
    cout<<"a2: "; 
    a2.show();
    a=a1+a2;
    cout<< "a: ";
    a.show();
    a=a1-a2;
    cout<<"a: ";
    a.show();
    return 0;
}
运行结果:

a1: (_x,_y)=(1,2)
a2: (_x,_y)=(4,5)
a: (_x,_y)=(5,7)
a: (_x,_y)=(-3,-3)

本例第 11~12 行代码将“+”和“−”运算符重载函数声明为类 A 的友元函数。将运算符重载函数声明为类的友元函数,与【示例1】重载为类的成员函数的用法和规则相同。

优秀文章