C++运算符重载的语义、语法和语用|C语法

  [摘 要] 文章针对C++运算符重载的a义、语法和语用进行全面详尽的介绍,为面向对象编程者在使用C++语言时对重载运算符这一难点的理解和使用上扫除障碍。   [关键词] C++ 运算符重载 编程 对象 operator 友元
  
  0.引言
  C++中预定义的运算符的操作对象只能是基本数据类型。但实际上,对于许多用户自定义类型(例如类),也需要类似的运算操作。这时就必须在C++中重新定义这些运算符,赋予已有运算符新的功能,使它能够用于特定类型执行特定的操作。运算符重载的实质是函数重载[1],它提供了C++的可扩展性,也是C++最吸引人的特性之一。
  1.C++运算符重载的语义
  所谓多态性[2]是指发出同样的消息被不同类型的对象接收时导致完全不同的行为。这里所说的消息主要是指对类的成员函数的调用,而不同的行为是指不同的实现。利用多态性,用户只需发送一般形式的消息,而将所有的实现留给接收消息的对象。对象根据所接收到的消息而做出相应的动作(即操作)。
  所谓函数重载简单地说就是赋给同一个函数名多个含义。具体地讲,C++中允许在相同的作用域内以相同的名字定义几个不同实现的函数,可以是成员函数,也可以是非成员函数。但是,定义这种重载函数时要求函数的参数或者至少有一个类型不同,或者个数不同。而对于返回值的类型没有要求,可以相同,也可以不同。那种参数个数和类型都相同,仅仅返回值不同的重载函数是非法的。因为编译程序在选择相同名字的重载函数时仅考虑函数表,这就是说要靠函数的参数表中,参数个数或参数类型的差异进行选择。由此可以看出,重载函数的意义在于它可以用相同的名字访问一组相互关联的函数,由编译程序来进行选择,因而这将有助于解决程序复杂性问题。如:在定义类时,构造函数重载给初始化带来了多种方式,为用户提供更大的灵活性。
  运算符重载就是赋予已有的运算符多重含义。C++中通过重新定义运算符,使它能够用于特定类的对象执行特定的功能,这便增强了C++语言的扩充能力。
  或者说,运算符重载允许C/C++的运算符在用户定义类型(类)上拥有一个用户自己定义的意义。
  2.C++运算符重载的语法
  运算符重载实际是一个函数,所以运算符的重载实际上是函数的重载。编译程序对运算符重载的选择,遵循着函数重载的选择原则。当遇到不很明显的运算时,编译程序将去寻找参数相匹配的运算符函数。
  运算符重载是通过创建运算符函数实现的,运算符函数定义了重载的运算符将要进行的操作。运算符函数的定义与其他函数的定义类似,惟一的区别是运算符函数的函数名是由关键字operator和其后要重载的运算符符号构成的。运算符函数定义的一般格式如下:
    operator ()
  {...
  
  }
  2.1运算符重载时要遵循以下规则[3]:
   (1) 除了类属关系运算符"."、成员指针运算符".*"、作用域运算符"::"、sizeof运算符和三目运算符"?:"以外,C++中的所有运算符都可以重载。
  
   (2) 重载运算符限制在C++语言中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符。
   (3) 运算符重载实质上是函数重载,因此编译程序对运算符重载的选择,遵循函数重载的选择原则。
   (4) 重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符操作数的个数及语法结构。
   (5) 运算符重载不能改变该运算符用于内部类型对象的含义。它只能和用户自定义类型的对象一起使用,或者用于用户自定义类型的对象和内部类型的对象混合使用时。
   (6) 运算符重载是针对新类型数据的实际需要对原有运算符进行的适当的改造,重载的功能应当与原有功能相类似,避免没有目的地使用重载运算符。重载的运算符可以和原来的运算符不一定有必然联系,例如我重载‘+’运算符,可以不做加法运算,而是把字符串连接起来。当然你要是用‘+’运算符来做减法运算,也是可以的,不过这不是明智之举。
  2.2运算符函数重载一般有两种形式:
  重载为类的成员函数和重载为类的非成员函数。非成员函数通常是友元[4]。(可以把一个运算符作为一个非成员、非友元函数重载。但是,这样的运算符函数访问类的私有和保护成员时,必须使用类的公有接口中提供的设置数据和读取数据的函数,调用这些函数时会降低性能。可以内联这些函数以提高性能。)   
  (1)成员函数运算符
  运算符重载为类的成员函数的一般格式为:
       operator ()
  {...
       
   }
  当运算符重载为类的成员函数时,函数的参数个数比原来的操作数要少一个(后置单目运算符除外),这是因为成员函数用this指针隐式地访问了类的一个对象,它充当了运算符函数最左边的操作数。因此:
  ① 双目运算符重载为类的成员函数时,函数只显式说明一个参数,该形参是运算符的右操作数。
  ② 前置单目运算符重载为类的成员函数时,不需要显式说明参数,即函数没有形参。
  ③ 后置单目运算符重载为类的成员函数时,函数要带有一个整型形参。
      调用成员函数运算符的格式如下:
     .operator ()
   它等价于
   
   例如:a+b等价于a.operator+(b)。一般情况下,我们采用运算符的习惯表达方式。
  (2)友元函数运算符
   运算符重载为类的友元函数的一般格式为:
       friend  operator ()
  {...
       
      }
  当运算符重载为类的友元函数时,由于没有隐含的this指针,因此操作数的个数没有变化,所有的操作数都必须通过函数的形参进行传递,函数的参数与操作数自左至右一一对应。
  调用友元函数运算符的格式如下:
  operator (,)
  它等价于
  
  例如:a+b等价于operator +(a,b)。
  (3)两种重载形式的比较
  在多数情况下,将运算符重载为类的成员函数和类的友元函数都是可以的。但成员函数运算符与友元函数运算符也具有各自的一些特点:
  (1) 一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。
  (2) 以下一些双目运算符不能重载为类的友元函数:=、()、[]、->。
  (3) 类型转换函数只能定义为一个类的成员函数而不能定义为类的友元函数。
  (4) 若一个运算符的操作需要修改对象的状态,选择重载为成员函数较好。
  (5) 若运算符所需的操作数(尤其是第一个操作数)希望有隐式类型转换,则只能选用友元函数。
  (6) 当运算符函数是一个成员函数时,最左边的操作数(或者只有最左边的操作数)必须是运算符类的一个类对象(或者是对该类对象的引用)。如果左边的操作数必须是一个不同类的对象,或者是一个内部类型的对象,该运算符函数必须作为一个友元函数来实现。
   (7) 当需要重载运算符具有可交换性时,选择重载为友元函数。
  3.C++运算符重载的语用
  3.1重载为类的成员函数
  这里举一个为了对分数进行四则运算而重载分数的运算符的例子。分数由分子和分母组成,可以定义一个分数类,然后再在类中重载分数四则运算的运算符。先看以下源代码:
  
  在程序中,类 fraction 定义了4个成员函数作为运算符重载函数。将运算符重载函数说明为类的成员函数格式如下:
  <类名> operator <运算符>(<参数表>)
  {……}
  其中,operator是定义运算符重载函数的关键字。
  程序中出现的表达式:
  c1+c2
  编译程序将给解释为:
  c1.operator+(c2)
  其中,c1和c2是 fraction 类的对象。operator+()是运算+的重载函数。
  该运算符重载函数仅有一个参数c2。可见,当重载为成员函数时,双目运算符仅有一个参数。对单目运算符,重载为成员函数时,不能再显式说明参数。重载为成员函数时,总是隐含了一个参数,该参数是this指针。this指针是指向调用该成员函数对象的指针。
  3.2重载为友元函数
  运算符重载函数还可以为友元函数。当重载友元函数时,将没有隐含的参数this指针。这样,对双目运算符,友元函数有2个参数,对单目运算符,友元函数有一个参数。但是,有些运行符不能重载为友元函数,它们是:=,(),[]和->。 重载为友元函数的运算符重载函数的定义格式如下:
  
  该程序的运行结果与上例相同。前面已讲过,对双目运算符,重载为成员函数时,仅一个参数,另一个被隐含;重载为友元函数时,有两个参数,没有隐含参数。因此,程序中出现的 c1+c2
  编译程序解释为:
  operator+(c1, c2)
  调用如下函数,进行求值,
  fraction operator +(const fraction &c1, const fraction &c2)
  4.结束语
  总之,函数重载和运算符重载是简单一类多态性。多态性是面向对象程序设计的重要特征之一。它与封装性和继承性构成了面向对象程序设计的三大特征。这三大特征是相互关联的。封装性是基础,继承性是关键,多态性是补充,而多态又必须存在于继承的环境之中。
  参考文献:
  [1]林锐 韩永泉 编著. 高质量程序设计指南-C++/C语言(第二版)[M]. 电子工业出版社,2003年6月第2版:282~283.
  [2]郑家瑜 编著.Visual C++入门与提高[M]. 中国铁道出版社,2002年9月第1版:472.
  [3]陈维兴 林小茶 编著.C++面向对象程序设计[M]. 中国铁道出版社,2004年6月第1版:214~215.
  [4]徐晓刚 高兆法 王秀娟 编著.Visual C++入门与提高[M]. 清华大学出版社,1999年5月第1版:30.
  基金项目:
  保山学院校级自然科学研究基金项目(项目编号:09B003JK)。
  作者简介:
  杨黎东(1965-),男,汉族,云南省保山人,讲师,主要研究领域为会计电算化、信息技术和教育。

推荐访问:重载 语义 语法 运算符