一,什么是运算符重载(operator overloading)

在软件开发过程中,运算符重载(英语:operator overloading)是多态的一种。运算符重载通常只是一种语法糖,这种语法对语言的功能没有影响,但是更方便程序员使用。让程序更加简洁,有更高的可读性。

二,语法糖的现实意义

在日常工作过程中,我们读代码读机会往往超过写代码,软件工程是门协作的艺术

我们写的代码主要是给机器和人看的,给机器看的可以通过代码测试和实际运行来进行检验,给人的目前还没太好的评价方式。不过在设计一门语言的时候,方便阅读也是语言设计重点考虑的一个方面。

运算符重载在功能实现方面并没有任何影响,但是会给未来的自己和其他程序员带来极大的便利。

三,operator关键字

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

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

使重载后的运算符的使用方法与重载前一致
扩展运算符的功能只能通过函数的方式实现

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

比如,我们要设计一个名为“person”的类,现在要判断person类的两个对象p1和p2是否一样大,我们设计的比较规则是按照其年龄来比较,那么,在设计person类的时候,就可以通过对操作符“==”进行重载,来使用操作符“==”对对象p1和p2

进行比较了(根据前面的分析,实际上比较的内容应该是person类中的数据成员“age”)。

我们上面说的对操作符“==”进行重载,说是“重载”,是由于编译器在实现操作符“==”功能的时候,已经为我们提供了这个操作符对于一些基本数据类型的操作支持,只不过由于现在该操作符所操作的内容变成了我们自定义的数据类型(如

class),而默认情况下,该操作符是不能对我们自定义的class类型进行操作的,所以,就需要我们通过重载该操作符,给出该操作符操作我们自定义的class类型的方法,从而达到使用该操作符对我们自定义的class类型进行运算的目的。

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

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

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

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

 bool operator==(const person& ps)
 {
   if (this->age == ps.age)
  {
      return true;
  }
      return false;
 }
示例代码operator_test2.cpp)如下:
class Person
{
   int age;
   public Person(int nAge){
         this->age = nAge;
   }
 
   bool operator==(Person ps){
   if (this.age == ps.age) {
        return true;
    }
        return false;
  }
};
 
int main()
{
    Person p1 = new Person(10);
    Person p2 = new Person(10);
    
    if (p1 == p2) {
    
     } else {
    
     }
    return 0;
}

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

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

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

示例代码如下:

class Person
{
  public int age;
};
 
// 左操作数的类型必须被显式指定
// 此处指定的类型为person类
bool operator==(Person p1 ,Person p2)
{
    if (p1.age == p2.age)
    {
        return true;
    }
    else
    {
        return false;
    }
}
 
int main()
{
    Person p1 = new Person();
    Person p2 = new Person();
    p1.age = 18;
    p2.age = 18;
 
    if (p1 == p2){
        
    }else{
}
return 0; }

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

五,Dart语言的运算符重载实例

第一步创建个类

class Role{
  final String name;
  final int accessLevel;
  
  const Role(this.name,this.accessLevel);
}

main()
{
  print('hello  operator overloading');
}

第二步 通过函数实现Role比较

class Role{
  final String name;
  final int accessLevel;
  
  const Role(this.name,this.accessLevel);
}

main()
{
  var adminRole =new Role('管理员',3);
  var reporterRole = new Role('报告员',2);
  var userRole= new Role('用户',1);
  if(adminRole.accessLevel > reporterRole.accessLevel){
    print("管理员的权限大于报告员");
  }  
  if(reporterRole.accessLevel > userRole.accessLevel){
    print("报告员的权限大于用户");
  }  
}

第三步 重载运算符

class Role {
  final String name;
  final int _accessLevel;

  const Role(this.name, this._accessLevel);
  bool operator >(Role Other) {
    return this._accessLevel > Other._accessLevel;
  }

  bool operator <(Role Other) {
    return this._accessLevel < Other._accessLevel;
  }
}

main() {
  var adminRole = new Role('管理员', 3);
  var reporterRole = new Role('报告员', 2);
  var userRole = new Role('用户', 1);
  if (adminRole > reporterRole) {
    print("管理员的权限大于报告员");
  }
  if (reporterRole > userRole) {
    print("报告员的权限大于用户");
  }
}