首页 > 编程笔记 > C++笔记 阅读:29

C++运算符重载详解(附带实例)

运算符实际上是一个函数,运算符重载本质上就是函数重载。函数重载可以让一个函数根据传入的参数执行不同的操作,运算符重载也一样。当遇到模糊运算时,编译程序会自动寻找与传入参数相匹配的运算符函数。

实际上,C++ 中已经对很多运算符进行了重载。例如,“+”可对不同类型的数据(如 int、float 等)进行加法操作;“<<”既是位移运算符,又可以配合 cout 向控制台输出数据。

C++ 中,数据类型分为基本数据类型和构造数据类型。其中,基本数据类型可以直接完成算术运算。例如,下面的代码实现了两个整型变量相加,输出结果为 30:
int a = 10, b = 20;
cout << a + b << endl;   // 两个整型变量相加

类属于用户构造的数据类型,类的两个对象能否通过“+”运算符直接进行求和呢?来看一下示例:
#include <iostream>
using namespace std;

class CBook                 // 定义CBook类
{
public:
    CBook(int iPage)        // 定义构造函数CBook(),初始化图书页码
    {
        m_iPage = iPage;
    }
    void display()          // 定义成员函数display(),显示图书页码
    {
        cout << m_iPage << endl;
    }

protected:
    int m_iPage;
};

int main()
{
    CBook bk1(10);          // 实例化CBook类对象bk1,页码为10
    CBook bk2(20);          // 实例化CBook类对象bk2,页码为20
    CBook tmp(0);           // 实例化CBook类对象tmp
    tmp = bk1 + bk2;        // 编译报错,两个对象不能直接相加
    tmp.display();
}
上述代码中,编译到“tmp=bk1+bk2;”时会报错,因为编译器不知道如何进行两个对象进行相加。

要实现两个类对象的相加有两种方法:一种是通过成员函数,另一种是重载“+”运算符。先来看下如何通过成员函数实现两个对象相加。代码如下:
#include <iostream>
using namespace std;

class CBook                 // 定义CBook类
{
public:
    CBook(int iPage)        // 定义构造函数CBook(),初始化图书页码
    {
        m_iPage = iPage;
    }

    int add(CBook a)        // 定义成员函数add(),通过引用成员变量进行相加
    {
        return m_iPage + a.m_iPage;
    }

protected:
    int m_iPage;
};

int main()
{
    CBook bk1(10);          // 实例化CBook类对象bk1,页码为10
    CBook bk2(20);          // 实例化CBook类对象bk2,页码为20
    cout << bk1.add(bk2) << endl;  // 调用成员函数add(),实现图书页码相加
}
程序虽然可以输出正确结果 30,但使用成员函数进行求和形式单一,代码不易复用。如果要实现多个对象的累加,其代码的可读性会大大降低。通过重载运算符就可以解决这些问题。

C++重载运算符的形式与规则

重载运算符的声明形式如下:
operator类型名();
operator 是需要重载的运算符,整个语句没有返回类型,因为类型名代表了它的返回类型。重载运算符将对象转换成类型名规定的类型,转换时的形式就像强制转换一样,如果没有重载运算符定义,直接用强制转换编译器将无法通过编译。

被重载的运算符只能是 C++ 中已有的运算符,具体如下:
重载运算符时不能改变运算符操作数的个数、原有的优先级、结合性和语法结构,即单目运算符只能重载为单目运算符,双目运算符只能重载为双目运算符。另外,重载运算符的含义必须清晰,不能有二义性。

注意,并非所有 C++ 运算符都可以重载,不允许重载的运算符有“.”、“.*”、“::”、“?”和“:”。


【实例】通过重载“+”运算符,实现两个 CBook 类对象的求和。具体代码如下:
#include <iostream>
using namespace std;

class CBook                 // 定义CBook类
{
public:
    CBook(int iPage)        // 定义构造函数,初始化图书页码
    {
        m_iPage = iPage;
    }

    CBook operator+(CBook b) // 重载“+”运算符
    {
        return CBook(m_iPage + b.m_iPage);
    }

    void display()          // 定义display()函数,显示图书页码
    {
        cout << m_iPage << endl;
    }

protected:
    int m_iPage;
};

int main()
{
    CBook bk1(10);          // 实例化CBook类对象bk1,页码为10
    CBook bk2(20);          // 实例化CBook类对象bk2,页码为20
    CBook tmp(0);           // 实例化CBook类对象tmp
    tmp = bk1 + bk2;        // 重载“+”后,bk1和bk2对象可以直接相加
    tmp.display();          // 调用CBook类的display()函数
}
程序运行结果为:

30

代码中,CBook 类重载了求和运算符“+”后,由它声明的两个对象 bk1 和 bk2 可以像两个整型变量一样直接相加。

C++重载运算符的运算

通过重载运算符,可以实现对象之间的运算,还可以实现对象和普通类型数据之间的运算。

例如:
#include <iostream>
using namespace std;

class CBook                 // 定义CBook类
{
public:
    int m_Pages;

    void OutputPages()      // 定义OutputPages(),输出图书页码
    {
        cout << m_Pages << endl;
    }

    CBook()                 // 定义构造函数,初始化图书页码
    {
        m_Pages = 0;
    }

    CBook operator+(const int page) // 重载“+”运算符
    {
        CBook bk;
        bk.m_Pages = m_Pages + page;
        return bk;
    }
};

int main()
{
    CBook vbBook, vfBook;   // 定义两个CBook类对象
    vfBook = vbBook + 10;   // 使用重载后的“+”,vbBook对象和10可以直接相加
    vfBook.OutputPages();   // 输出增加10页后的页码
}
通过修改运算符的参数为整数类型,可以实现 CBook 对象与整数相加。

对于两个整型变量相加,用户可以调换两个加数的顺序,因为加法符合交换律。但是,对于通过重载运算符实现的两个不同类型的对象相加则不能。因此,下面的语句是非法的:
vfBook = 10 + vbBook;   // 非法的代码

“++”和“--”运算符涉及前置运算和后置运算,重载这类运算符时该如何进行区分呢?默认情况下,如果重载运算符没有参数,则表示是前置运算。例如:
void operator++()   // 前置运算
{
    ++m_Pages;
}

如果重载运算符使用整数作参数,则表示是后置运算。注意,此时的参数值只是一个标识(标识后置运算),可以忽略。
void operator++(int)    // 后置运算
{
    ++m_Pages;
}

默认情况下,将一个整数赋值给一个对象是非法的,但通过重载“=”运算符可以将其变为合法。例如:
void operator=(int page)    // 重载赋值运算符
{
    m_Pages = page;
}

C++ 程序中,借助复制构造函数可以将一个对象复制成另一个对象。通过重载赋值运算符,也可以将一个整型数复制给一个对象。例如:
#include <iostream>
using namespace std;

class CBook                 // 定义CBook类
{
public:
    int m_Pages;

    void OutputPages()      // 定义成员函数OutputPages()
    {
        cout << m_Pages << endl;
    }

    CBook(int page)         // 构造函数
    {
        m_Pages = page;
    }

    void operator=(const int page)  // 重载“=”运算符
    {
        m_Pages = page;
    }
};

int main()                  // 主函数
{
    CBook mybk(0);          // 定义CBook类对象mybk
    mybk = 100;             // 使用重载运算符“=”,为mybk对象赋值
    mybk.OutputPages();     // 调用OutputPages()函数
}
程序中重载了“=”运算符,给 mybk 对象赋值 100,并通过 OutputPages() 成员函数将该值输出。

还可以通过重载构造函数将一个整数赋值给一个对象。例如:
#include <iostream>
using namespace std;

class CBook                 // 定义CBook类
{
public:
    int m_Pages;

    void OutputPages()      // 定义OutputPages()成员函数
    {
        cout << m_Pages << endl;
    }

    CBook()                 // 默认构造函数
    {
    }

    CBook(int page)         // 带参构造函数
    {
        m_Pages = page;
    }
};

int main()                  // 主函数
{
    CBook vbBook;           // 调用CBook
    vbBook = 200;
    vbBook.OutputPages();
}
程序中定义了一个重载的构造函数,以一个整数作为函数参数,这可以将一个整数赋值给一个 CBook 类对象。语句“vbBook = 200;”将调用构造函数 CBook(int page) 重新构造一个 CBook 对象,并将其赋值给 vbBook 对象。

相关文章