C++ operator(重载操作符)

1. 重载操作符

1.1 what

operator 是C++的一个关键字,它和运算符(如=)一起使用,表示一个运算符重载函数,在理解时可将operator和运算符(如operator=)视为一个函数名。

使用operator重载运算符,是C++扩展运算符功能的方法。使用operator扩展运算符功能的原因如下:

使重载后的运算符的使用方法与重载前一致
扩展运算符的功能只能通过函数的方式实现(实际上,C++中各种“功能”都是由函数实现的)

1.2 why

对于C++提供的所有操作符,通常只支持对于基本数据类型和标准库中提供的类的操作,而对于用户自己定义的类,如果想要通过该操作符实现一些基本操作(比如比较大小,判断是否相等),就需要用户自己来定义关于这个操作符的具体实现了。

比如,我们要设计一个名为“person”的类,现在要判断person类的两个对象p1和p2是否一样大,我们设计的比较规则是按照其年龄来比较,那么,在设计person类的时候,就可以通过对操作符“== ”进行重载,来使用操作符“==”对对象p1和p2进行比较了(根据前面的分析,实际上比较的内容应该是person类中的数据成员“age”)。

我们上面说的对操作符 “ == ” 进行重载,说是“重载”,是由于编译器在实现操作符“==”功能的时候,已经为我们提供了这个操作符对于一些基本数据类型的操作支持,只不过由于现在该操作符所操作的内容变成了我们自定义的数据类型(如class),而默认情况下,该操作符是不能对我们自定义的class类型进行操作的,所以,就需要我们通过重载该操作符,给出该操作符操作我们自定义的class类型的方法,从而达到使用该操作符对我们自定义的class类型进行运算的目的。

1.3 how

实现一个操作符重载的方式通常分为两种情况:

  • 将操作符重载实现为类的成员函数;
  • 操作符重载实现为非类的成员函数(即全局函数)。

1.3.1 将操作符重载实现为类的成员函数

在类体中声明(定义)需要重载的操作符,声明方式跟普通的成员函数一样,只不过操作符重载函数的名字是“关键字 operator +以及紧跟其后的一个C++预定义的操作符”,样式如下(person是我们定义的类):

bool operator==(const person& ps)
{
    if (this->age == ps.age)
    {
        return true;
    }
    return false;
}

示例代码(operator_test2.cpp)如下:

  #include <iostream>
     
    using namespace std;
     
    class person
    {
    private:
        int age;
    public:
        person(int nAge)
        {
            this->age = nAge;
        }
     
    bool operator==(const person& ps)
    {
        if (this->age == ps.age)
        {
            return true;
        }
        return false;
    }
    };

 

    int main()
    {
        person p1(10);
        person p2(10);
    
    if (p1 == p2)
    {
        cout << "p1 is equal with p2." << endl;
 
    }
    else
    {
        cout << "p1 is not equal with p2." << endl;
    }
    
    return 0;
    }

 

因为操作符重载函数“operator==”是person类的一个成员函数,所以对象p1、p2都可以调用该函数。其中的 if (p1 == p2) 语句,相当于对象p1调用函数“operator==”,把对象p2作为一个参数传递给该函数,从而实现了两个对象的比较。

1.3.2 操作符重载实现为非类的成员函数(即全局函数)

对于全局重载操作符,代表左操作数的参数必须被显式指定。

示例代码如下:

 #include <iostream>
     
    using namespace std;
     
    class person
    {
    public:
        int age;
    };
     
    // 左操作数的类型必须被显式指定
    // 此处指定的类型为person类
    bool operator==(person const& p1 ,person const& p2)
    {
        if (p1.age == p2.age)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
     
    int main()
    {
        person p1;
        person p2;
        p1.age = 18;
        p2.age = 18;
     
    if (p1 == p2)
    {
        cout << "p1 is equal with p2." << endl;
    }
    else
    {
        cout << "p1 is NOT equal with p2." << endl;
    }
 
    return 0;
    }

1.3.4 操作符重载的方式选择

可以根据以下因素,确定把一个操作符重载为类的成员函数还是全局函数:

  • 如果一个重载操作符是类成员,那么只有当与它一起使用的左操作数是该类的对象时,该操作符才会被调用;而如果该操作符的左操作数确定为其他的类型,则操作符必须被重载为全局函数;
  • C++要求’=’、’[]’、’()’、’->'操作符必须被定义为类的成员操作符,把这些操作符通过全局函数进行重载时会出现编译错误
  • 如果有一个操作数是类类型(如string类),那么对于对称操作符(比如==操作符),最好通过全局函数的方式进行重载。

1.3.5 操作符重载的限制

实现操作符重载时,需要注意:

  • 重载后操作符的操作数至少有一个是用户定义类型;
  • 不能违反原来操作数的语法规则;
  • 不能创建新的操作符;
  • 不能重载的操作符包括(以空格分隔):sizeof . .* :: ?: RTTI类型运算符
  • =、()、[]、以及 ->操作符只能被类的成员函数重载

2.函数对象

重载()操作符的类,它的对象叫做函数对象,即它是 类似于函数的 对象(它可以向函数一样调用),也叫作仿函数。

注意:函数对象(仿函数)是一个类,不是一个函数。
与普通函数相比,函数对象比函数更加灵活,函数对象的优势:

  1. 函数对象可以有自己的状态。我们可以在类中定义状态变量,这样一个函数对象在多次的调用中可以共享这个状态;
  2. 函数对象有自己特有的类型。我们可以传递相应的类型作为参数来实例化相应的模板,比如说带参数的函数形参

重载操作符()有一个参数,称为一元仿函数,有两个参数,就叫二元仿函数。

#include <bits/stdc++.h>

using namespace std;
struct Print
{
	int num; // 保存运行的次数
	Print()
	{
		num = 0;
	}
	void operator()(int val)
	{
		num++;
	}
};
int main()
{
	Print myprint;
	vector<int> v1;
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(40);
	Print myprint2 = for_each(v1.begin(), v1.end(), myprint); //遍历算法,函数对象作为参数,返回值也是函数对象
	cout << myprint2.num << endl; //打印出调用的次数,结果num=4
	return 0;
}

  • 14
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值