C++ 面向对象的三个特点--多态性(二)

时间:2021-04-25 00:14:38
  • 运算符重载

运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。

  1. 类外部的运算符重载

首先,我们通过一个例子来说明为什么要有运算符重载。

 1 // Complex.h
 2 class Complex
 3 {
 4 public:
 5     int a;
 6     int b;
 7     Complex(int i = 0, int j = 0)
 8     {   a = i;b = j; }
 9 };
10 // main
11 #include "stdafx.h"
12 #include "stdlib.h"
13 #include "Complex.h"
14 // 类外部定义的运算符重载
15 Complex operator+(Complex c1, Complex c2)
16 {
17     Complex temp;
18     temp.a = c1.a + c2.a;
19     temp.b = c1.b + c2.b;
20     return temp;
21 }
22 
23 int _tmain(int argc, _TCHAR* argv[])
24 {
25     Complex com1(1, 3), com2(2,4);
26     Complex total;
27     total = com1 + com2;
28     printf("total.a = %d, total.b = %d\n", total.a, total.b);
29 
30     system("pause");
31     return 0;
32 }

说明:

C++知道如何把两个int型数据相加,但是他们不能把两个类Complex直接相加,运算符重载就是为了解决这种类似的问题,也极大的丰富了运算符的特性。

C++语言对运算符重载的规则:

(1).运算符重载是针对新类型数据的需要,对原有运算符进行适当的改造完成的。一般来讲,重载的功能应当与原来的功能类似。

(2).C++语言中只能重载原先已经定义了的运算符,程序员不能自己臆造新的运算符来扩充C++语言。

(3).以下的几个运算符是不能重载的:类属关系运算符“.”、成员指针运算符“*”、作用域分辨符“::”、sizeof运算符和三目运算符“?:”。

(4).不能改变运算符的操作个数。

(5).不能改变运算符的原有优先级。

(6).不能改变运算符的原有结合特性。

2. 友元运算符函数

我们上面看到的运算符重载是在类的外部定义的,它只能访问类中的公有成员数据。实际上,运算符重载函数一般采用以下两种形式:一是成员运算符函数重载,而是友元运算符函数重载。

友元运算符函数的定义规则是:

类的内部声明格式

Class X{

// ···

Friend 返回类型 operator 运算符(形参表)

// ···};

类的外部定义格式

返回类型 operator 运算符(形参表)

{

    函数体

}

友元函数不是该类的成员函数,所以在类外部定义是不需要写上这个类的类名,由于友元函数没有this指针,所以如果友元运算符函数重载的是双目运算符,则参数表中有两个操作数,如果是单目运算符,则是一个操作数。

 1 // Complex.h
 2 class Complex
 3 {
 4 public:
 5     Complex(int i = 0, int j = 0)
 6     {
 7        a = i;
 8        b = j;
 9     }
10 
11     friend Complex operator+(Complex c1, Complex c2);
12 public:
13     int a;
14     int b;
15 };
16 // Complex.cpp
17 #include "StdAfx.h"
18 #include "Complex.h"
19 Complex operator+(Complex c1, Complex c2)
20 {
21     Complex temp;
22     temp.a = c1.a + c2.a;
23     temp.b = c1.b + c2.b;
24     return temp;
25 }
26 // main
27 int _tmain(int argc, _TCHAR* argv[])
28 {
29     Complex com1(1, 3), com2(2,4);
30     Complex total;
31     total = com1 + com2;
32     printf("total.a = %d, total.b = %d\n", total.a, total.b);
33     system("pause");
34     return 0;
35 }

有一个需要注意的地方,就是友元函数重载“++”、“--”这样的运算符,可能会出现问题。

说明:

(1). 运算符重载可以返回任何类型,但通常与他所操作的类的类型相同。

(2). 重载运算符时,最好保持运算符的原含义,以防混淆。

(3). C++中,用户不能定义新的运算符,只能从已有的运算符中选择一个恰当的运算符进行重载。

(4). 不能用友元函数重载以下运算符:=,(),[],->

3.成员运算符重载

把运算符函数定义为某个类的成员函数,称为成员运算符重载。

 1 // Complex.h
 2 class Complex
 3 {
 4 public:
 5     Complex(int i = 0, int j = 0)
 6     {
 7        a = i;
 8        b = j;
 9     }
10     Complex operator+(Complex c);
11 
12 public:
13     int a;
14     int b;
15 };
16 // Complex.cpp
17 #include "StdAfx.h"
18 #include "Complex.h"
19 
20 Complex Complex::operator+(Complex c)
21 {
22     Complex temp;
23     temp.a = a + c.a;
24     temp.b = b + c.b;
25     return temp;
26 }
27 // main
28 int _tmain(int argc, _TCHAR* argv[])
29 {
30     Complex com1(1, 3), com2(2,4);
31     Complex total;
32     total = com1 + com2;
33     printf("total.a = %d, total.b = %d\n", total.a, total.b);
34     system("pause");
35     return 0;
36 }

我们来比较以下成员运算符函数与友元运算符函数的差别:

对双目运算符而言,成员运算符函数由于有this指针,所以只带有一个参数,而友元运算符函数带有两个参数。对单目运算符而言,成员运算符函数不带参数,而友元运算符函数带一个参数。