需要解决的问题:
第一种解决方案:
运行结果如下:
上图中将a和b定义成公有的暴露出来不符合面向对象封装的原则。
第二种方案如下:
虽然解决了复数相加的问题,但是并不完美,显得不自然,我们能否使用c1+c2的这种方式呢?
思考:
操作符重载:
重载的深层次意义就在于可以扩展系统已经存在的功能。
用operator定义的函数就直接用来重载操作符了。
示例:
1 #include <stdio.h> 2 3 class Complex 4 { 5 int a; 6 int b; 7 public: 8 Complex(int a = 0, int b = 0) 9 { 10 this->a = a; 11 this->b = b; 12 } 13 14 int getA() 15 { 16 return a; 17 } 18 19 int getB() 20 { 21 return b; 22 } 23 24 friend Complex operator + (const Complex& p1, const Complex& p2); 25 }; 26 27 Complex operator + (const Complex& p1, const Complex& p2) 28 { 29 Complex ret; 30 31 ret.a = p1.a + p2.a; 32 ret.b = p1.b + p2.b; 33 34 return ret; 35 } 36 37 int main() 38 { 39 40 Complex c1(1, 2); 41 Complex c2(3, 4); 42 Complex c3 = c1 + c2; // operator + (c1, c2) 43 44 printf("c3.a = %d, c3.b = %d ", c3.getA(), c3.getB()); 45 46 return 0; 47 }
我们只是将第二个解决方案中的Add换成了operator +,这就完成了重载。
运行结果如下:
我们将主函数改成c1+c2的形式:
依然编译运行通过了。
当编译器看到c1 + c2时,发现c1和c2不是基本类型,它本身不能完成这两个数的加法,于是就开始去查找有没有这个+的重载,于是就调用到了重载函数。
上面的额重载是全局函数,而且使用了友元,现在继续改进:
编译器优先在成员函数中寻找操作符重载函数。
示例:
运行结果如下:
将全局函数的重载和类成员函数的重载全部定义:
1 #include <stdio.h> 2 3 class Complex 4 { 5 int a; 6 int b; 7 public: 8 Complex(int a = 0, int b = 0) 9 { 10 this->a = a; 11 this->b = b; 12 } 13 14 int getA() 15 { 16 return a; 17 } 18 19 int getB() 20 { 21 return b; 22 } 23 24 Complex operator + (const Complex& p) 25 { 26 Complex ret; 27 printf("Complex operator + (const Complex& p) "); 28 ret.a = this->a + p.a; 29 ret.b = this->b + p.b; 30 31 return ret; 32 } 33 34 friend Complex operator + (const Complex& p1, const Complex& p2); 35 }; 36 37 Complex operator + (const Complex& p1, const Complex& p2) 38 { 39 Complex ret; 40 printf("Complex operator + (const Complex& p1, const Complex& p2) "); 41 ret.a = p1.a + p2.a; 42 ret.b = p1.b + p2.b; 43 44 return ret; 45 } 46 47 int main() 48 { 49 50 Complex c1(1, 2); 51 Complex c2(3, 4); 52 Complex c3 = c1 + c2; // c1.operator + (c2) 53 54 printf("c3.a = %d, c3.b = %d ", c3.getA(), c3.getB()); 55 56 return 0; 57 }
运行结果如下:
可以看到优先调用的是成员函数的重载操作符。
小结: